0
# Data Encoding
1
2
SJCL provides comprehensive encoding and decoding capabilities for converting between bit arrays and various string formats including UTF-8, Base64, hexadecimal, Base32, and binary formats.
3
4
## Capabilities
5
6
### UTF-8 String Encoding
7
8
Convert between UTF-8 strings and SJCL's internal bit array format.
9
10
```javascript { .api }
11
/**
12
* Convert UTF-8 string to bit array
13
* @param {string} str - UTF-8 string to convert
14
* @returns {BitArray} String data as bit array
15
*/
16
sjcl.codec.utf8String.toBits(str);
17
18
/**
19
* Convert bit array to UTF-8 string
20
* @param {BitArray} arr - Bit array to convert
21
* @returns {string} UTF-8 encoded string
22
*/
23
sjcl.codec.utf8String.fromBits(arr);
24
```
25
26
**Usage Examples:**
27
28
```javascript
29
const sjcl = require('sjcl');
30
31
// String to bit array conversion
32
const text = "Hello, ไธ็! ๐";
33
const bits = sjcl.codec.utf8String.toBits(text);
34
console.log("Bits:", bits); // Array of 32-bit integers
35
36
// Bit array back to string
37
const decoded = sjcl.codec.utf8String.fromBits(bits);
38
console.log("Decoded:", decoded); // "Hello, ไธ็! ๐"
39
40
// Use with encryption
41
const key = sjcl.random.randomWords(8);
42
const plaintext = sjcl.codec.utf8String.toBits("Secret message");
43
const encrypted = sjcl.encrypt("password", sjcl.codec.utf8String.fromBits(plaintext));
44
```
45
46
### Hexadecimal Encoding
47
48
Convert between hexadecimal strings and bit arrays for readable binary data representation.
49
50
```javascript { .api }
51
/**
52
* Convert hexadecimal string to bit array
53
* @param {string} str - Hexadecimal string (case insensitive, spaces/0x ignored)
54
* @returns {BitArray} Binary data as bit array
55
*/
56
sjcl.codec.hex.toBits(str);
57
58
/**
59
* Convert bit array to hexadecimal string
60
* @param {BitArray} arr - Bit array to convert
61
* @returns {string} Lowercase hexadecimal string
62
*/
63
sjcl.codec.hex.fromBits(arr);
64
```
65
66
**Usage Examples:**
67
68
```javascript
69
const sjcl = require('sjcl');
70
71
// Hex string to bit array
72
const hexString = "deadbeef";
73
const hexBits = sjcl.codec.hex.toBits(hexString);
74
console.log("Hex bits:", hexBits);
75
76
// Bit array to hex string
77
const hexDecoded = sjcl.codec.hex.fromBits(hexBits);
78
console.log("Hex decoded:", hexDecoded); // "deadbeef"
79
80
// Hash to hex example
81
const hash = sjcl.hash.sha256.hash("Hello, World!");
82
const hexHash = sjcl.codec.hex.fromBits(hash);
83
console.log("SHA-256 hex:", hexHash);
84
85
// Flexible hex input (spaces, 0x prefix, mixed case)
86
const flexHex = sjcl.codec.hex.toBits("0xDEAD BEEF cafe");
87
console.log("Flexible hex:", sjcl.codec.hex.fromBits(flexHex));
88
```
89
90
### Base64 Encoding
91
92
Standard Base64 encoding for binary data transmission and storage.
93
94
```javascript { .api }
95
/**
96
* Convert bit array to Base64 string
97
* @param {BitArray} arr - Bit array to encode
98
* @param {boolean} [_noEquals] - Omit padding equals signs
99
* @param {boolean} [_url] - Use URL-safe Base64 alphabet
100
* @returns {string} Base64 encoded string
101
*/
102
sjcl.codec.base64.fromBits(arr, _noEquals, _url);
103
104
/**
105
* Convert Base64 string to bit array
106
* @param {string} str - Base64 string to decode
107
* @param {boolean} [_url] - Use URL-safe Base64 alphabet
108
* @returns {BitArray} Decoded binary data as bit array
109
* @throws {sjcl.exception.invalid} If Base64 string is invalid
110
*/
111
sjcl.codec.base64.toBits(str, _url);
112
```
113
114
**Usage Examples:**
115
116
```javascript
117
const sjcl = require('sjcl');
118
119
// Basic Base64 encoding
120
const data = sjcl.codec.utf8String.toBits("Hello, World!");
121
const base64 = sjcl.codec.base64.fromBits(data);
122
console.log("Base64:", base64); // "SGVsbG8sIFdvcmxkIQ=="
123
124
// Base64 decoding
125
const decoded = sjcl.codec.base64.toBits(base64);
126
const text = sjcl.codec.utf8String.fromBits(decoded);
127
console.log("Decoded:", text); // "Hello, World!"
128
129
// Base64 without padding
130
const noPadding = sjcl.codec.base64.fromBits(data, true);
131
console.log("No padding:", noPadding); // "SGVsbG8sIFdvcmxkIQ"
132
133
// URL-safe Base64
134
const urlSafe = sjcl.codec.base64.fromBits(data, false, true);
135
console.log("URL-safe:", urlSafe); // Uses - and _ instead of + and /
136
```
137
138
### Base64URL Encoding
139
140
URL and filename safe Base64 encoding variant.
141
142
```javascript { .api }
143
/**
144
* Convert bit array to Base64URL string
145
* @param {BitArray} arr - Bit array to encode
146
* @returns {string} Base64URL encoded string (no padding)
147
*/
148
sjcl.codec.base64url.fromBits(arr);
149
150
/**
151
* Convert Base64URL string to bit array
152
* @param {string} str - Base64URL string to decode
153
* @returns {BitArray} Decoded binary data as bit array
154
*/
155
sjcl.codec.base64url.toBits(str);
156
```
157
158
**Usage Examples:**
159
160
```javascript
161
const sjcl = require('sjcl');
162
163
// Base64URL encoding (commonly used in JWT tokens)
164
const payload = sjcl.codec.utf8String.toBits('{"sub":"1234567890","name":"John Doe"}');
165
const base64url = sjcl.codec.base64url.fromBits(payload);
166
console.log("Base64URL:", base64url); // URL-safe, no padding
167
168
// JWT-style usage
169
function createJWTPayload(data) {
170
const payloadBits = sjcl.codec.utf8String.toBits(JSON.stringify(data));
171
return sjcl.codec.base64url.fromBits(payloadBits);
172
}
173
174
const tokenPayload = createJWTPayload({
175
sub: "user123",
176
exp: Math.floor(Date.now() / 1000) + 3600
177
});
178
```
179
180
### Base32 Encoding
181
182
Base32 encoding for use cases requiring case-insensitive alphanumeric encoding.
183
184
```javascript { .api }
185
/**
186
* Convert bit array to Base32 string
187
* @param {BitArray} arr - Bit array to encode
188
* @param {boolean} [_noEquals] - Omit padding equals signs
189
* @param {boolean} [_hex] - Use Base32hex alphabet instead of standard
190
* @returns {string} Base32 encoded string
191
*/
192
sjcl.codec.base32.fromBits(arr, _noEquals, _hex);
193
194
/**
195
* Convert Base32 string to bit array
196
* @param {string} str - Base32 string to decode (case insensitive)
197
* @param {boolean} [_hex] - Use Base32hex alphabet instead of standard
198
* @returns {BitArray} Decoded binary data as bit array
199
* @throws {sjcl.exception.invalid} If Base32 string is invalid
200
*/
201
sjcl.codec.base32.toBits(str, _hex);
202
```
203
204
**Base32Hex variant:**
205
206
```javascript { .api }
207
/**
208
* Convert bit array to Base32hex string
209
* @param {BitArray} arr - Bit array to encode
210
* @param {boolean} [_noEquals] - Omit padding equals signs
211
* @returns {string} Base32hex encoded string
212
*/
213
sjcl.codec.base32hex.fromBits(arr, _noEquals);
214
215
/**
216
* Convert Base32hex string to bit array
217
* @param {string} str - Base32hex string to decode
218
* @returns {BitArray} Decoded binary data as bit array
219
*/
220
sjcl.codec.base32hex.toBits(str);
221
```
222
223
**Usage Examples:**
224
225
```javascript
226
const sjcl = require('sjcl');
227
228
// Standard Base32 encoding
229
const data = sjcl.codec.utf8String.toBits("Hello, World!");
230
const base32 = sjcl.codec.base32.fromBits(data);
231
console.log("Base32:", base32); // "JBSWY3DPEBLW64TMMQQQ===="
232
233
// Base32 decoding (case insensitive)
234
const base32Lower = base32.toLowerCase();
235
const decoded = sjcl.codec.base32.toBits(base32Lower);
236
console.log("Decoded:", sjcl.codec.utf8String.fromBits(decoded));
237
238
// Base32hex (uses 0-9 and A-V instead of A-Z and 2-7)
239
const base32hex = sjcl.codec.base32hex.fromBits(data);
240
console.log("Base32hex:", base32hex);
241
242
// Without padding
243
const noPadding = sjcl.codec.base32.fromBits(data, true);
244
console.log("No padding:", noPadding);
245
```
246
247
### Byte Array Encoding
248
249
Convert between bit arrays and regular JavaScript byte arrays.
250
251
```javascript { .api }
252
/**
253
* Convert bit array to byte array
254
* @param {BitArray} arr - Bit array to convert
255
* @returns {number[]} Array of bytes (0-255)
256
*/
257
sjcl.codec.bytes.fromBits(arr);
258
259
/**
260
* Convert byte array to bit array
261
* @param {number[]} bytes - Array of bytes (0-255)
262
* @returns {BitArray} Bit array representation
263
*/
264
sjcl.codec.bytes.toBits(bytes);
265
```
266
267
**Usage Examples:**
268
269
```javascript
270
const sjcl = require('sjcl');
271
272
// Bit array to byte array
273
const bits = sjcl.codec.utf8String.toBits("Hello!");
274
const bytes = sjcl.codec.bytes.fromBits(bits);
275
console.log("Bytes:", bytes); // [72, 101, 108, 108, 111, 33]
276
277
// Byte array to bit array
278
const backToBits = sjcl.codec.bytes.toBits(bytes);
279
const text = sjcl.codec.utf8String.fromBits(backToBits);
280
console.log("Back to text:", text); // "Hello!"
281
282
// Working with binary data
283
const binaryData = [0xFF, 0xFE, 0xFD, 0xFC];
284
const binaryBits = sjcl.codec.bytes.toBits(binaryData);
285
const hexView = sjcl.codec.hex.fromBits(binaryBits);
286
console.log("Hex view:", hexView); // "fffefdfc"
287
```
288
289
### ArrayBuffer Encoding
290
291
Convert between bit arrays and ArrayBuffer objects for modern binary data handling.
292
293
```javascript { .api }
294
/**
295
* Convert bit array to ArrayBuffer
296
* @param {BitArray} arr - Bit array to convert
297
* @param {boolean} [padding] - Add padding if needed
298
* @param {number} [padding_count] - Number of padding bytes
299
* @returns {ArrayBuffer} ArrayBuffer containing binary data
300
*/
301
sjcl.codec.arrayBuffer.fromBits(arr, padding, padding_count);
302
303
/**
304
* Convert ArrayBuffer to bit array
305
* @param {ArrayBuffer} buffer - ArrayBuffer to convert
306
* @returns {BitArray} Bit array representation
307
*/
308
sjcl.codec.arrayBuffer.toBits(buffer);
309
310
/**
311
* Generate hex dump of ArrayBuffer contents
312
* @param {ArrayBuffer} buffer - ArrayBuffer to dump
313
* @returns {string} Hex dump string for debugging
314
*/
315
sjcl.codec.arrayBuffer.hexDumpBuffer(buffer);
316
```
317
318
**Usage Examples:**
319
320
```javascript
321
const sjcl = require('sjcl');
322
323
// Bit array to ArrayBuffer
324
const bits = sjcl.codec.utf8String.toBits("Hello, ArrayBuffer!");
325
const buffer = sjcl.codec.arrayBuffer.fromBits(bits);
326
console.log("Buffer length:", buffer.byteLength);
327
328
// ArrayBuffer to bit array
329
const backToBits = sjcl.codec.arrayBuffer.toBits(buffer);
330
const text = sjcl.codec.utf8String.fromBits(backToBits);
331
console.log("Decoded:", text);
332
333
// Hex dump for debugging
334
const hexDump = sjcl.codec.arrayBuffer.hexDumpBuffer(buffer);
335
console.log("Hex dump:", hexDump);
336
337
// Working with TypedArrays
338
const uint8Array = new Uint8Array(buffer);
339
console.log("First bytes:", Array.from(uint8Array.slice(0, 5)));
340
```
341
342
### Z85 Encoding
343
344
Z85 encoding (ZeroMQ Base85) for compact binary data representation.
345
346
```javascript { .api }
347
/**
348
* Convert bit array to Z85 string
349
* @param {BitArray} arr - Bit array to encode (length must be multiple of 4 bytes)
350
* @returns {string} Z85 encoded string
351
* @throws {sjcl.exception.invalid} If data length is not multiple of 4 bytes
352
*/
353
sjcl.codec.z85.fromBits(arr);
354
355
/**
356
* Convert Z85 string to bit array
357
* @param {string} str - Z85 string to decode
358
* @returns {BitArray} Decoded binary data as bit array
359
* @throws {sjcl.exception.invalid} If Z85 string is invalid
360
*/
361
sjcl.codec.z85.toBits(str);
362
```
363
364
**Usage Examples:**
365
366
```javascript
367
const sjcl = require('sjcl');
368
369
// Z85 encoding (data must be multiple of 4 bytes)
370
const data = sjcl.random.randomWords(2); // 8 bytes = 64 bits
371
const z85 = sjcl.codec.z85.fromBits(data);
372
console.log("Z85:", z85);
373
374
// Z85 decoding
375
const decoded = sjcl.codec.z85.toBits(z85);
376
console.log("Equal:", sjcl.bitArray.equal(data, decoded));
377
378
// Padding data to 4-byte boundary
379
function padToZ85(bits) {\n const bitLength = sjcl.bitArray.bitLength(bits);\n const byteLength = Math.ceil(bitLength / 8);\n const paddedByteLength = Math.ceil(byteLength / 4) * 4;\n const paddedBitLength = paddedByteLength * 8;\n \n return sjcl.bitArray.clamp(sjcl.bitArray.concat(bits, [0]), paddedBitLength);\n}\n\nconst text = sjcl.codec.utf8String.toBits(\"Hello\"); // 5 bytes\nconst padded = padToZ85(text);\nconst z85Text = sjcl.codec.z85.fromBits(padded);\n```\n\n## Common Encoding Patterns\n\n### Multi-format Conversion\n\nConvert data between multiple formats:\n\n```javascript\nconst sjcl = require('sjcl');\n\nfunction convertFormats(data, fromFormat, toFormat) {\n let bits;\n \n // Convert from source format to bit array\n switch (fromFormat) {\n case 'utf8':\n bits = sjcl.codec.utf8String.toBits(data);\n break;\n case 'hex':\n bits = sjcl.codec.hex.toBits(data);\n break;\n case 'base64':\n bits = sjcl.codec.base64.toBits(data);\n break;\n case 'base32':\n bits = sjcl.codec.base32.toBits(data);\n break;\n default:\n throw new Error('Unknown source format');\n }\n \n // Convert from bit array to target format\n switch (toFormat) {\n case 'utf8':\n return sjcl.codec.utf8String.fromBits(bits);\n case 'hex':\n return sjcl.codec.hex.fromBits(bits);\n case 'base64':\n return sjcl.codec.base64.fromBits(bits);\n case 'base32':\n return sjcl.codec.base32.fromBits(bits);\n case 'bytes':\n return sjcl.codec.bytes.fromBits(bits);\n default:\n throw new Error('Unknown target format');\n }\n}\n\n// Usage\nconst hex = convertFormats(\"Hello, World!\", 'utf8', 'hex');\nconst base64 = convertFormats(hex, 'hex', 'base64');\nconst text = convertFormats(base64, 'base64', 'utf8');\nconsole.log(text); // \"Hello, World!\"\n```\n\n### Safe Encoding with Validation\n\nValidate and safely encode/decode data:\n\n```javascript\nconst sjcl = require('sjcl');\n\nclass SafeEncoder {\n static encodeText(text, format = 'base64') {\n if (typeof text !== 'string') {\n throw new sjcl.exception.invalid('Input must be a string');\n }\n \n const bits = sjcl.codec.utf8String.toBits(text);\n \n switch (format.toLowerCase()) {\n case 'hex':\n return sjcl.codec.hex.fromBits(bits);\n case 'base64':\n return sjcl.codec.base64.fromBits(bits);\n case 'base32':\n return sjcl.codec.base32.fromBits(bits);\n default:\n throw new sjcl.exception.invalid('Unsupported format');\n }\n }\n \n static decodeText(encoded, format = 'base64') {\n try {\n let bits;\n \n switch (format.toLowerCase()) {\n case 'hex':\n bits = sjcl.codec.hex.toBits(encoded);\n break;\n case 'base64':\n bits = sjcl.codec.base64.toBits(encoded);\n break;\n case 'base32':\n bits = sjcl.codec.base32.toBits(encoded);\n break;\n default:\n throw new sjcl.exception.invalid('Unsupported format');\n }\n \n return sjcl.codec.utf8String.fromBits(bits);\n } catch (e) {\n throw new sjcl.exception.corrupt('Invalid encoded data: ' + e.message);\n }\n }\n}\n\n// Usage\ntry {\n const encoded = SafeEncoder.encodeText(\"Hello, World!\", 'base64');\n const decoded = SafeEncoder.decodeText(encoded, 'base64');\n console.log('Success:', decoded);\n} catch (e) {\n console.error('Encoding error:', e.message);\n}\n```\n\n## Performance Considerations\n\n- **UTF-8**: Fastest for text data\n- **Hex**: Good for debugging and human-readable binary data\n- **Base64**: Standard for binary data transmission\n- **Base32**: Case-insensitive, good for user input\n- **Z85**: Most compact for binary data\n- **ArrayBuffer**: Best for modern JavaScript binary data handling\n\n## Security Considerations\n\n1. **Data Validation**: Always validate input before decoding\n2. **Error Handling**: Handle encoding/decoding errors gracefully\n3. **Memory**: Be aware of memory usage with large data\n4. **Timing**: Encoding/decoding operations are not constant-time\n5. **Character Sets**: Ensure proper UTF-8 handling for international text