| 83 | /// Decodes a Base32 string. Padding and whitespace are tolerated; mixed |
| 84 | /// case is accepted. |
| 85 | public static byte[] decode(String s) { |
| 86 | if (s == null) { |
| 87 | return new byte[0]; |
| 88 | } |
| 89 | // strip padding and whitespace |
| 90 | StringBuilder cleaned = new StringBuilder(s.length()); |
| 91 | for (int i = 0; i < s.length(); i++) { |
| 92 | char c = s.charAt(i); |
| 93 | if (c == '=' || c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '-') { |
| 94 | continue; |
| 95 | } |
| 96 | cleaned.append(c); |
| 97 | } |
| 98 | int len = cleaned.length(); |
| 99 | byte[] out = new byte[len * 5 / 8]; |
| 100 | int bits = 0; |
| 101 | int value = 0; |
| 102 | int pos = 0; |
| 103 | for (int i = 0; i < len; i++) { |
| 104 | char c = cleaned.charAt(i); |
| 105 | if (c >= DECODE.length || DECODE[c] < 0) { |
| 106 | throw new CryptoException("invalid Base32 character: " + c); |
| 107 | } |
| 108 | value = (value << 5) | DECODE[c]; |
| 109 | bits += 5; |
| 110 | if (bits >= 8) { |
| 111 | out[pos++] = (byte) ((value >>> (bits - 8)) & 0xff); |
| 112 | bits -= 8; |
| 113 | } |
| 114 | } |
| 115 | return out; |
| 116 | } |
| 117 | } |