Skip to content

Commit c71756f

Browse files
committed
Update README.md
1 parent 8213826 commit c71756f

File tree

1 file changed

+255
-1
lines changed

1 file changed

+255
-1
lines changed

README.md

Lines changed: 255 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,257 @@
11
# CodexKotlin
22

3-
CodexKotlin is a Kotlin implementation of Operator's Codex, a text-to-text format-transforming-encryption library.
3+
CodexKotlin is a Kotlin implementation of Operator's Codex, a text-to-text format-transforming-encryption library. CodexKotlin enables encoding arbitrary data into various constrained text formats for transmission through restrictive channels.
4+
5+
## Overview
6+
7+
CodexKotlin is part of the Operator Foundation's Codex project, which provides format-transforming encryption capabilities. This library encodes binary data into structured text formats that can pass through systems with strict formatting requirements, such as:
8+
9+
- WSPR (Weak Signal Propagation Reporter) messages for amateur radio
10+
- SMS-compatible text formats
11+
- Email-safe encodings
12+
- Other constrained communication channels
13+
14+
## Installation
15+
16+
Add to your `build.gradle`:
17+
18+
```gradle
19+
dependencies {
20+
implementation 'org.operatorfoundation:codex:1.0.0'
21+
}
22+
```
23+
24+
## Core Components
25+
26+
### Symbol System
27+
28+
CodexKotlin uses a flexible symbol system that defines encoding constraints for different formats. Symbols can represent:
29+
- Fixed characters (Required)
30+
- Letter/number combinations (CallLetterNumber)
31+
- Grid coordinates (GridLetter)
32+
- Numeric values (Number)
33+
- Power levels (Power)
34+
35+
### Encoder/Decoder
36+
37+
The core `Encoder` and `Decoder` classes transform between binary data and symbol-constrained formats:
38+
39+
```kotlin
40+
val symbols = listOf(/* symbol definitions */)
41+
val encoder = Encoder(symbols)
42+
val decoder = Decoder(symbols)
43+
44+
// Encode data to symbols
45+
val data = BigInteger("12345")
46+
val encoded = encoder.encode(data)
47+
48+
// Decode back
49+
val decoded = decoder.decode(encoded)
50+
```
51+
52+
## WSPR Implementation
53+
54+
The library includes a complete WSPR message codec as a reference implementation:
55+
56+
### WSPRCodex
57+
58+
Encodes arbitrary binary data into WSPR message format.
59+
60+
```kotlin
61+
import org.operatorfoundation.codex.WSPRCodex
62+
63+
val codex = WSPRCodex()
64+
65+
// Encode any binary data
66+
val data = "Hello World!".toByteArray()
67+
val messages = codex.encode(data)
68+
69+
// Messages are in WSPR format
70+
messages.forEach { msg ->
71+
println("Callsign: ${msg.callsign}")
72+
println("Grid: ${msg.gridSquare}")
73+
println("Power: ${msg.powerDbm} dBm")
74+
}
75+
76+
// Decode back to original
77+
val decoded = codex.decode(messages)
78+
```
79+
80+
### Multi-Message Support
81+
82+
For data larger than a single format frame, CodexKotlin automatically chunks and reassembles:
83+
84+
```kotlin
85+
val largeData = ByteArray(100) { it.toByte() }
86+
val messages = codex.encode(largeData) // Automatically chunks
87+
88+
// Handles out-of-order reception
89+
val shuffled = messages.shuffled()
90+
val decoded = codex.decode(shuffled) // Reassembles correctly
91+
```
92+
93+
### Capacity
94+
95+
WSPR mode supports:
96+
- **Basic Mode**: Up to 64 bytes (16 messages × 4 bytes/message)
97+
- **Extended Mode**: Up to 768 bytes (256 messages × 3 bytes/message)
98+
99+
## Custom Format Support
100+
101+
You can define your own symbol constraints for other formats:
102+
103+
```kotlin
104+
// Define symbols for your format
105+
val customSymbols = listOf(
106+
Required('!'.code.toByte()), // Fixed prefix
107+
Letter(), // A-Z only
108+
Number(), // 0-9 only
109+
AlphaNumeric() // A-Z, 0-9
110+
)
111+
112+
val encoder = Encoder(customSymbols)
113+
val decoder = Decoder(customSymbols)
114+
```
115+
116+
## Architecture
117+
118+
```
119+
CodexKotlin
120+
├── Core
121+
│ ├── Encoder/Decoder - Core transformation engine
122+
│ ├── Symbol System - Format constraint definitions
123+
│ └── BigInteger Math - Numeric representation
124+
125+
└── Implementations
126+
├── WSPRCodex - WSPR radio messages (public API)
127+
├── WSPRMultiMessageCodex - Chunking/reassembly (internal class)
128+
└── [Extensible for other formats]
129+
```
130+
131+
## Use Cases
132+
133+
- **Amateur Radio**: Send data via WSPR, FT8, or other weak-signal modes
134+
- **Emergency Communications**: Encode messages for transmission through limited channels
135+
- **Steganography**: Hide data within format-compliant text
136+
- **IoT Telemetry**: Send sensor data through SMS or other text-only channels
137+
- **Censorship Circumvention**: Transform data to pass through restrictive filters
138+
139+
## API Reference
140+
141+
### WSPRCodex Methods
142+
143+
#### `encode(data: ByteArray, messageId: Byte? = null): List<WSPRDataMessage>`
144+
145+
Encodes binary data into WSPR messages.
146+
147+
**Parameters:**
148+
- `data`: Binary data to encode
149+
- `messageId`: Optional ID for message grouping (auto-generated if null)
150+
151+
**Returns:** List of WSPR messages
152+
153+
#### `decode(messages: List<WSPRDataMessage>): ByteArray`
154+
155+
Decodes WSPR messages back to binary data.
156+
157+
**Parameters:**
158+
- `messages`: List of WSPR messages (order doesn't matter)
159+
160+
**Returns:** Original binary data
161+
162+
### WSPRDataMessage Properties
163+
164+
```kotlin
165+
data class WSPRDataMessage(
166+
val callsign: String, // 6 characters max
167+
val gridSquare: String, // 4 characters (Maidenhead)
168+
val powerDbm: Int // 0-60 dBm
169+
)
170+
```
171+
172+
## Transmission Time
173+
174+
Each WSPR message requires 2 minutes to transmit:
175+
176+
| Data Size | Messages | Transmission Time |
177+
|-----------|----------|------------------|
178+
| 1-4 bytes | 1 | 2 minutes |
179+
| 5-8 bytes | 2 | 4 minutes |
180+
| 20 bytes | 5 | 10 minutes |
181+
| 64 bytes | 16 | 32 minutes |
182+
| 768 bytes | 256 | 8.5 hours |
183+
184+
## Error Handling
185+
186+
```kotlin
187+
try {
188+
val encoded = codex.encode(data)
189+
} catch (e: WSPRCodexException) {
190+
// Handle encoding errors
191+
}
192+
193+
try {
194+
val decoded = codex.decode(messages)
195+
} catch (e: WSPRMultiMessageException) {
196+
// Handle incomplete or corrupted messages
197+
}
198+
```
199+
200+
## Example: Encrypted Communication
201+
202+
```kotlin
203+
import org.operatorfoundation.codex.WSPRCodex
204+
import javax.crypto.Cipher
205+
import javax.crypto.spec.SecretKeySpec
206+
207+
fun encryptAndTransmit(plaintext: String, key: ByteArray) {
208+
// Encrypt
209+
val cipher = Cipher.getInstance("AES")
210+
cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"))
211+
val encrypted = cipher.doFinal(plaintext.toByteArray())
212+
213+
// Encode to WSPR
214+
val codex = WSPRCodex()
215+
val messages = codex.encode(encrypted)
216+
217+
// Transmit each message
218+
messages.forEach { msg ->
219+
transmitWSPR(msg.callsign, msg.gridSquare, msg.powerDbm)
220+
}
221+
}
222+
223+
fun receiveAndDecrypt(messages: List<WSPRDataMessage>, key: ByteArray): String {
224+
// Decode from WSPR
225+
val codex = WSPRCodex()
226+
val encrypted = codex.decode(messages)
227+
228+
// Decrypt
229+
val cipher = Cipher.getInstance("AES")
230+
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"))
231+
val decrypted = cipher.doFinal(encrypted)
232+
233+
return String(decrypted)
234+
}
235+
```
236+
237+
## Limitations
238+
239+
- Some formats may lose trailing zeros in data
240+
- Each format has maximum capacity constraints
241+
- All chunks must be received for successful multi-message decoding
242+
- WSPR format limited to ~50 bits per message
243+
244+
## Contributing
245+
246+
CodexKotlin is part of the Operator Foundation's suite of tools for unrestricted internet access. Contributions are welcome.
247+
248+
## Related Projects
249+
250+
- **Codex** (Swift): Original implementation
251+
- **CodexPython**: Python implementation
252+
- **AudioCoder**: Audio signal generation for encoded messages
253+
- **TransmissionAndroid**: Android USB serial communication
254+
255+
## License
256+
257+
MIT License

0 commit comments

Comments
 (0)