diff options
Diffstat (limited to 'src/org/xbill/DNS/utils/base32.java')
-rw-r--r-- | src/org/xbill/DNS/utils/base32.java | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/src/org/xbill/DNS/utils/base32.java b/src/org/xbill/DNS/utils/base32.java new file mode 100644 index 0000000..a2f26ea --- /dev/null +++ b/src/org/xbill/DNS/utils/base32.java @@ -0,0 +1,213 @@ +// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org) + +package org.xbill.DNS.utils; + +import java.io.*; + +/** + * Routines for converting between Strings of base32-encoded data and arrays + * of binary data. This currently supports the base32 and base32hex alphabets + * specified in RFC 4648, sections 6 and 7. + * + * @author Brian Wellington + */ + +public class base32 { + +public static class Alphabet { + private Alphabet() {} + + public static final String BASE32 = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="; + public static final String BASE32HEX = + "0123456789ABCDEFGHIJKLMNOPQRSTUV="; +}; + +private String alphabet; +private boolean padding, lowercase; + +/** + * Creates an object that can be used to do base32 conversions. + * @param alphabet Which alphabet should be used + * @param padding Whether padding should be used + * @param lowercase Whether lowercase characters should be used. + * default parameters (The standard base32 alphabet, no padding, uppercase) + */ +public +base32(String alphabet, boolean padding, boolean lowercase) { + this.alphabet = alphabet; + this.padding = padding; + this.lowercase = lowercase; +} + +static private int +blockLenToPadding(int blocklen) { + switch (blocklen) { + case 1: + return 6; + case 2: + return 4; + case 3: + return 3; + case 4: + return 1; + case 5: + return 0; + default: + return -1; + } +} + +static private int +paddingToBlockLen(int padlen) { + switch (padlen) { + case 6: + return 1; + case 4: + return 2; + case 3: + return 3; + case 1: + return 4; + case 0: + return 5; + default : + return -1; + } +} + +/** + * Convert binary data to a base32-encoded String + * + * @param b An array containing binary data + * @return A String containing the encoded data + */ +public String +toString(byte [] b) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + for (int i = 0; i < (b.length + 4) / 5; i++) { + short s[] = new short[5]; + int t[] = new int[8]; + + int blocklen = 5; + for (int j = 0; j < 5; j++) { + if ((i * 5 + j) < b.length) + s[j] = (short) (b[i * 5 + j] & 0xFF); + else { + s[j] = 0; + blocklen--; + } + } + int padlen = blockLenToPadding(blocklen); + + // convert the 5 byte block into 8 characters (values 0-31). + + // upper 5 bits from first byte + t[0] = (byte) ((s[0] >> 3) & 0x1F); + // lower 3 bits from 1st byte, upper 2 bits from 2nd. + t[1] = (byte) (((s[0] & 0x07) << 2) | ((s[1] >> 6) & 0x03)); + // bits 5-1 from 2nd. + t[2] = (byte) ((s[1] >> 1) & 0x1F); + // lower 1 bit from 2nd, upper 4 from 3rd + t[3] = (byte) (((s[1] & 0x01) << 4) | ((s[2] >> 4) & 0x0F)); + // lower 4 from 3rd, upper 1 from 4th. + t[4] = (byte) (((s[2] & 0x0F) << 1) | ((s[3] >> 7) & 0x01)); + // bits 6-2 from 4th + t[5] = (byte) ((s[3] >> 2) & 0x1F); + // lower 2 from 4th, upper 3 from 5th; + t[6] = (byte) (((s[3] & 0x03) << 3) | ((s[4] >> 5) & 0x07)); + // lower 5 from 5th; + t[7] = (byte) (s[4] & 0x1F); + + // write out the actual characters. + for (int j = 0; j < t.length - padlen; j++) { + char c = alphabet.charAt(t[j]); + if (lowercase) + c = Character.toLowerCase(c); + os.write(c); + } + + // write out the padding (if any) + if (padding) { + for (int j = t.length - padlen; j < t.length; j++) + os.write('='); + } + } + + return new String(os.toByteArray()); +} + +/** + * Convert a base32-encoded String to binary data + * + * @param str A String containing the encoded data + * @return An array containing the binary data, or null if the string is invalid + */ +public byte[] +fromString(String str) { + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + byte [] raw = str.getBytes(); + for (int i = 0; i < raw.length; i++) + { + char c = (char) raw[i]; + if (!Character.isWhitespace(c)) { + c = Character.toUpperCase(c); + bs.write((byte) c); + } + } + + if (padding) { + if (bs.size() % 8 != 0) + return null; + } else { + while (bs.size() % 8 != 0) + bs.write('='); + } + + byte [] in = bs.toByteArray(); + + bs.reset(); + DataOutputStream ds = new DataOutputStream(bs); + + for (int i = 0; i < in.length / 8; i++) { + short[] s = new short[8]; + int[] t = new int[5]; + + int padlen = 8; + for (int j = 0; j < 8; j++) { + char c = (char) in[i * 8 + j]; + if (c == '=') + break; + s[j] = (short) alphabet.indexOf(in[i * 8 + j]); + if (s[j] < 0) + return null; + padlen--; + } + int blocklen = paddingToBlockLen(padlen); + if (blocklen < 0) + return null; + + // all 5 bits of 1st, high 3 (of 5) of 2nd + t[0] = (s[0] << 3) | s[1] >> 2; + // lower 2 of 2nd, all 5 of 3rd, high 1 of 4th + t[1] = ((s[1] & 0x03) << 6) | (s[2] << 1) | (s[3] >> 4); + // lower 4 of 4th, high 4 of 5th + t[2] = ((s[3] & 0x0F) << 4) | ((s[4] >> 1) & 0x0F); + // lower 1 of 5th, all 5 of 6th, high 2 of 7th + t[3] = (s[4] << 7) | (s[5] << 2) | (s[6] >> 3); + // lower 3 of 7th, all of 8th + t[4] = ((s[6] & 0x07) << 5) | s[7]; + + try { + for (int j = 0; j < blocklen; j++) + ds.writeByte((byte) (t[j] & 0xFF)); + } + catch (IOException e) { + } + } + + return bs.toByteArray(); +} + +} |