1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.util.encoders; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.IOException; 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.OutputStream; 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class HexEncoder 7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam implements Encoder 8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam protected final byte[] encodingTable = 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', 12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam }; 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /* 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * set up the decoding table. 17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam protected final byte[] decodingTable = new byte[128]; 19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam protected void initialiseDecodingTable() 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 2270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom for (int i = 0; i < decodingTable.length; i++) 2370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 2470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom decodingTable[i] = (byte)0xff; 2570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 2670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = 0; i < encodingTable.length; i++) 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam decodingTable[encodingTable[i]] = (byte)i; 30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam decodingTable['A'] = decodingTable['a']; 33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam decodingTable['B'] = decodingTable['b']; 34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam decodingTable['C'] = decodingTable['c']; 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam decodingTable['D'] = decodingTable['d']; 36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam decodingTable['E'] = decodingTable['e']; 37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam decodingTable['F'] = decodingTable['f']; 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public HexEncoder() 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam initialiseDecodingTable(); 43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * encode the input data producing a Hex output stream. 47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the number of bytes produced. 49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int encode( 51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] data, 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int off, 53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int length, 54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam OutputStream out) 55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IOException 56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = off; i < (off + length); i++) 58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int v = data[i] & 0xff; 60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam out.write(encodingTable[(v >>> 4)]); 62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam out.write(encodingTable[v & 0xf]); 63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return length * 2; 66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 6870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private static boolean ignore( 69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam char c) 70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 7170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return c == '\n' || c =='\r' || c == '\t' || c == ' '; 72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 7370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * decode the Hex encoded byte data writing it to the given output stream, 76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * whitespace characters will be ignored. 77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the number of bytes produced. 79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int decode( 81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] data, 82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int off, 83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int length, 84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam OutputStream out) 85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IOException 86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte b1, b2; 88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int outLen = 0; 89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int end = off + length; 91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam while (end > off) 93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (!ignore((char)data[end - 1])) 95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam break; 97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam end--; 100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int i = off; 103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam while (i < end) 104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam while (i < end && ignore((char)data[i])) 106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam i++; 108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam b1 = decodingTable[data[i++]]; 111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam while (i < end && ignore((char)data[i])) 113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam i++; 115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam b2 = decodingTable[data[i++]]; 118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 11970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if ((b1 | b2) < 0) 12070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 12170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom throw new IOException("invalid characters encountered in Hex data"); 12270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 12370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam out.write((b1 << 4) | b2); 125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam outLen++; 127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return outLen; 130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * decode the Hex encoded String data writing it to the given output stream, 134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * whitespace characters will be ignored. 135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the number of bytes produced. 137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int decode( 139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam String data, 140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam OutputStream out) 141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IOException 142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte b1, b2; 144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int length = 0; 145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int end = data.length(); 147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam while (end > 0) 149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (!ignore(data.charAt(end - 1))) 151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam break; 153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam end--; 156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int i = 0; 159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam while (i < end) 160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam while (i < end && ignore(data.charAt(i))) 162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam i++; 164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam b1 = decodingTable[data.charAt(i++)]; 167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam while (i < end && ignore(data.charAt(i))) 169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam i++; 171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam b2 = decodingTable[data.charAt(i++)]; 174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 17570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if ((b1 | b2) < 0) 17670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 17770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom throw new IOException("invalid characters encountered in Hex string"); 17870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 17970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam out.write((b1 << 4) | b2); 181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam length++; 183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return length; 186b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 188