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