1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.codec.binary;
19
20 import org.apache.commons.codec.CodecPolicy;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class Base32 extends BaseNCodec {
45
46
47
48
49
50 private static final int BITS_PER_ENCODED_BYTE = 5;
51 private static final int BYTES_PER_ENCODED_BLOCK = 8;
52 private static final int BYTES_PER_UNENCODED_BLOCK = 5;
53
54
55
56
57
58
59 private static final byte[] DECODE_TABLE = {
60
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64 -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1,
65 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
66 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
67 -1, -1, -1, -1, -1,
68 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
69 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
70 };
71
72
73
74
75
76
77
78 private static final byte[] ENCODE_TABLE = {
79 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
80 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
81 '2', '3', '4', '5', '6', '7',
82 };
83
84
85
86
87
88
89
90 private static final byte[] HEX_DECODE_TABLE = {
91
92 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
93 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
94 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
95 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
96 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
97 25, 26, 27, 28, 29, 30, 31,
98 -1, -1, -1, -1, -1, -1, -1, -1, -1,
99 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
100 25, 26, 27, 28, 29, 30, 31
101 };
102
103
104
105
106
107
108
109 private static final byte[] HEX_ENCODE_TABLE = {
110 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
111 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
112 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
113 };
114
115
116
117 private static final int MASK_5BITS = 0x1f;
118
119
120 private static final long MASK_4BITS = 0x0fL;
121
122
123 private static final long MASK_3BITS = 0x07L;
124
125
126 private static final long MASK_2BITS = 0x03L;
127
128
129 private static final long MASK_1BITS = 0x01L;
130
131
132
133
134
135
136
137
138
139 private final int decodeSize;
140
141
142
143
144 private final byte[] decodeTable;
145
146
147
148
149
150 private final int encodeSize;
151
152
153
154
155 private final byte[] encodeTable;
156
157
158
159
160 private final byte[] lineSeparator;
161
162
163
164
165
166
167
168 public Base32() {
169 this(false);
170 }
171
172
173
174
175
176
177
178
179
180 public Base32(final boolean useHex) {
181 this(0, null, useHex, PAD_DEFAULT);
182 }
183
184
185
186
187
188
189
190
191
192
193 public Base32(final boolean useHex, final byte padding) {
194 this(0, null, useHex, padding);
195 }
196
197
198
199
200
201
202
203
204
205 public Base32(final byte pad) {
206 this(false, pad);
207 }
208
209
210
211
212
213
214
215
216
217
218 public Base32(final int lineLength) {
219 this(lineLength, CHUNK_SEPARATOR);
220 }
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236 public Base32(final int lineLength, final byte[] lineSeparator) {
237 this(lineLength, lineSeparator, false, PAD_DEFAULT);
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex) {
256 this(lineLength, lineSeparator, useHex, PAD_DEFAULT);
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275 public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex, final byte padding) {
276 this(lineLength, lineSeparator, useHex, padding, DECODING_POLICY_DEFAULT);
277 }
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297 public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex, final byte padding, final CodecPolicy decodingPolicy) {
298 super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, lineSeparator == null ? 0 : lineSeparator.length, padding, decodingPolicy);
299 if (useHex) {
300 this.encodeTable = HEX_ENCODE_TABLE;
301 this.decodeTable = HEX_DECODE_TABLE;
302 } else {
303 this.encodeTable = ENCODE_TABLE;
304 this.decodeTable = DECODE_TABLE;
305 }
306 if (lineLength > 0) {
307 if (lineSeparator == null) {
308 throw new IllegalArgumentException("lineLength " + lineLength + " > 0, but lineSeparator is null");
309 }
310
311 if (containsAlphabetOrPad(lineSeparator)) {
312 final String sep = StringUtils.newStringUtf8(lineSeparator);
313 throw new IllegalArgumentException("lineSeparator must not contain Base32 characters: [" + sep + "]");
314 }
315 this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
316 this.lineSeparator = lineSeparator.clone();
317 } else {
318 this.encodeSize = BYTES_PER_ENCODED_BLOCK;
319 this.lineSeparator = null;
320 }
321 this.decodeSize = this.encodeSize - 1;
322
323 if (isInAlphabet(padding) || Character.isWhitespace(padding)) {
324 throw new IllegalArgumentException("pad must not be in alphabet or whitespace");
325 }
326 }
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347 @Override
348 void decode(final byte[] input, int inPos, final int inAvail, final Context context) {
349
350
351 if (context.eof) {
352 return;
353 }
354 if (inAvail < 0) {
355 context.eof = true;
356 }
357 for (int i = 0; i < inAvail; i++) {
358 final byte b = input[inPos++];
359 if (b == pad) {
360
361 context.eof = true;
362 break;
363 }
364 final byte[] buffer = ensureBufferSize(decodeSize, context);
365 if (b >= 0 && b < this.decodeTable.length) {
366 final int result = this.decodeTable[b];
367 if (result >= 0) {
368 context.modulus = (context.modulus + 1) % BYTES_PER_ENCODED_BLOCK;
369
370 context.lbitWorkArea = (context.lbitWorkArea << BITS_PER_ENCODED_BYTE) + result;
371 if (context.modulus == 0) {
372 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 32 & MASK_8BITS);
373 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 24 & MASK_8BITS);
374 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 16 & MASK_8BITS);
375 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 8 & MASK_8BITS);
376 buffer[context.pos++] = (byte) (context.lbitWorkArea & MASK_8BITS);
377 }
378 }
379 }
380 }
381
382
383
384
385 if (context.eof && context.modulus > 0) {
386 final byte[] buffer = ensureBufferSize(decodeSize, context);
387
388
389
390
391
392
393
394 switch (context.modulus) {
395
396 case 1:
397 validateTrailingCharacters();
398 case 2:
399 validateCharacter(MASK_2BITS, context);
400 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 2 & MASK_8BITS);
401 break;
402 case 3:
403 validateTrailingCharacters();
404
405 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 7 & MASK_8BITS);
406 break;
407 case 4:
408 validateCharacter(MASK_4BITS, context);
409 context.lbitWorkArea = context.lbitWorkArea >> 4;
410 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 8 & MASK_8BITS);
411 buffer[context.pos++] = (byte) (context.lbitWorkArea & MASK_8BITS);
412 break;
413 case 5:
414 validateCharacter(MASK_1BITS, context);
415 context.lbitWorkArea = context.lbitWorkArea >> 1;
416 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 16 & MASK_8BITS);
417 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 8 & MASK_8BITS);
418 buffer[context.pos++] = (byte) (context.lbitWorkArea & MASK_8BITS);
419 break;
420 case 6:
421 validateTrailingCharacters();
422
423 context.lbitWorkArea = context.lbitWorkArea >> 6;
424 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 16 & MASK_8BITS);
425 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 8 & MASK_8BITS);
426 buffer[context.pos++] = (byte) (context.lbitWorkArea & MASK_8BITS);
427 break;
428 case 7:
429 validateCharacter(MASK_3BITS, context);
430 context.lbitWorkArea = context.lbitWorkArea >> 3;
431 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 24 & MASK_8BITS);
432 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 16 & MASK_8BITS);
433 buffer[context.pos++] = (byte) (context.lbitWorkArea >> 8 & MASK_8BITS);
434 buffer[context.pos++] = (byte) (context.lbitWorkArea & MASK_8BITS);
435 break;
436 default:
437
438 throw new IllegalStateException("Impossible modulus " + context.modulus);
439 }
440 }
441 }
442
443
444
445
446
447
448
449
450
451
452
453
454 @Override
455 void encode(final byte[] input, int inPos, final int inAvail, final Context context) {
456
457
458 if (context.eof) {
459 return;
460 }
461
462
463 if (inAvail < 0) {
464 context.eof = true;
465 if (0 == context.modulus && lineLength == 0) {
466 return;
467 }
468 final byte[] buffer = ensureBufferSize(encodeSize, context);
469 final int savedPos = context.pos;
470 switch (context.modulus) {
471 case 0:
472 break;
473 case 1:
474 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 3) & MASK_5BITS];
475 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea << 2) & MASK_5BITS];
476 buffer[context.pos++] = pad;
477 buffer[context.pos++] = pad;
478 buffer[context.pos++] = pad;
479 buffer[context.pos++] = pad;
480 buffer[context.pos++] = pad;
481 buffer[context.pos++] = pad;
482 break;
483 case 2:
484 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 11) & MASK_5BITS];
485 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 6) & MASK_5BITS];
486 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 1) & MASK_5BITS];
487 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea << 4) & MASK_5BITS];
488 buffer[context.pos++] = pad;
489 buffer[context.pos++] = pad;
490 buffer[context.pos++] = pad;
491 buffer[context.pos++] = pad;
492 break;
493 case 3:
494 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 19) & MASK_5BITS];
495 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 14) & MASK_5BITS];
496 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 9) & MASK_5BITS];
497 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 4) & MASK_5BITS];
498 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea << 1) & MASK_5BITS];
499 buffer[context.pos++] = pad;
500 buffer[context.pos++] = pad;
501 buffer[context.pos++] = pad;
502 break;
503 case 4:
504 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 27) & MASK_5BITS];
505 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 22) & MASK_5BITS];
506 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 17) & MASK_5BITS];
507 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 12) & MASK_5BITS];
508 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 7) & MASK_5BITS];
509 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 2) & MASK_5BITS];
510 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea << 3) & MASK_5BITS];
511 buffer[context.pos++] = pad;
512 break;
513 default:
514 throw new IllegalStateException("Impossible modulus " + context.modulus);
515 }
516 context.currentLinePos += context.pos - savedPos;
517
518 if (lineLength > 0 && context.currentLinePos > 0) {
519 System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
520 context.pos += lineSeparator.length;
521 }
522 } else {
523 for (int i = 0; i < inAvail; i++) {
524 final byte[] buffer = ensureBufferSize(encodeSize, context);
525 context.modulus = (context.modulus + 1) % BYTES_PER_UNENCODED_BLOCK;
526 int b = input[inPos++];
527 if (b < 0) {
528 b += 256;
529 }
530 context.lbitWorkArea = (context.lbitWorkArea << 8) + b;
531 if (0 == context.modulus) {
532 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 35) & MASK_5BITS];
533 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 30) & MASK_5BITS];
534 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 25) & MASK_5BITS];
535 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 20) & MASK_5BITS];
536 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 15) & MASK_5BITS];
537 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 10) & MASK_5BITS];
538 buffer[context.pos++] = encodeTable[(int) (context.lbitWorkArea >> 5) & MASK_5BITS];
539 buffer[context.pos++] = encodeTable[(int) context.lbitWorkArea & MASK_5BITS];
540 context.currentLinePos += BYTES_PER_ENCODED_BLOCK;
541 if (lineLength > 0 && lineLength <= context.currentLinePos) {
542 System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
543 context.pos += lineSeparator.length;
544 context.currentLinePos = 0;
545 }
546 }
547 }
548 }
549 }
550
551
552
553
554
555
556
557 @Override
558 public boolean isInAlphabet(final byte octet) {
559 return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
560 }
561
562
563
564
565
566
567
568
569
570
571
572
573
574 private void validateCharacter(final long emptyBitsMask, final Context context) {
575
576 if (isStrictDecoding() && (context.lbitWorkArea & emptyBitsMask) != 0) {
577 throw new IllegalArgumentException("Strict decoding: Last encoded character (before the paddings if any) is a valid " +
578 "base 32 alphabet but not a possible encoding. Expected the discarded bits from the character to be zero.");
579 }
580 }
581
582
583
584
585
586
587 private void validateTrailingCharacters() {
588 if (isStrictDecoding()) {
589 throw new IllegalArgumentException("Strict decoding: Last encoded character(s) (before the paddings if any) are valid " +
590 "base 32 alphabet but not a possible encoding. Decoding requires either 2, 4, 5, or 7 trailing 5-bit characters to create bytes.");
591 }
592 }
593 }