initial checkin
[org.ibex.nanogoat.git] / src / org / bouncycastle / util / encoders / Base64.java
1 package org.bouncycastle.util.encoders;
2
3 public class Base64
4 {
5         private static final byte[] encodingTable =
6                 {
7                     (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
8             (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
9             (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
10             (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
11                     (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
12             (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
13             (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
14             (byte)'v',
15                     (byte)'w', (byte)'x', (byte)'y', (byte)'z',
16                     (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
17             (byte)'7', (byte)'8', (byte)'9',
18                     (byte)'+', (byte)'/'
19                 };
20
21         /**
22          * encode the input data producong a base 64 encoded byte array.
23          *
24          * @return a byte array containing the base 64 encoded data.
25          */
26         public static byte[] encode(
27                 byte[]  data)
28         {
29                 byte[]  bytes;
30                 
31                 int modulus = data.length % 3;
32                 if (modulus == 0)
33                 {
34                         bytes = new byte[4 * data.length / 3];
35                 }
36                 else
37                 {
38                         bytes = new byte[4 * ((data.length / 3) + 1)];
39                 }
40
41         int dataLength = (data.length - modulus);
42                 int a1, a2, a3;
43                 for (int i = 0, j = 0; i < dataLength; i += 3, j += 4)
44                 {
45                         a1 = data[i] & 0xff;
46                         a2 = data[i + 1] & 0xff;
47                         a3 = data[i + 2] & 0xff;
48
49                         bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
50                         bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
51                         bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
52                         bytes[j + 3] = encodingTable[a3 & 0x3f];
53                 }
54
55                 /*
56                  * process the tail end.
57                  */
58                 int     b1, b2, b3;
59                 int     d1, d2;
60
61                 switch (modulus)
62                 {
63                 case 0:         /* nothing left to do */
64                         break;
65                 case 1:
66                         d1 = data[data.length - 1] & 0xff;
67                         b1 = (d1 >>> 2) & 0x3f;
68                         b2 = (d1 << 4) & 0x3f;
69
70                         bytes[bytes.length - 4] = encodingTable[b1];
71                         bytes[bytes.length - 3] = encodingTable[b2];
72                         bytes[bytes.length - 2] = (byte)'=';
73                         bytes[bytes.length - 1] = (byte)'=';
74                         break;
75                 case 2:
76                         d1 = data[data.length - 2] & 0xff;
77                         d2 = data[data.length - 1] & 0xff;
78
79                         b1 = (d1 >>> 2) & 0x3f;
80                         b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
81                         b3 = (d2 << 2) & 0x3f;
82
83                         bytes[bytes.length - 4] = encodingTable[b1];
84                         bytes[bytes.length - 3] = encodingTable[b2];
85                         bytes[bytes.length - 2] = encodingTable[b3];
86                         bytes[bytes.length - 1] = (byte)'=';
87                         break;
88                 }
89
90                 return bytes;
91         }
92
93         /*
94          * set up the decoding table.
95          */
96         private static final byte[] decodingTable;
97
98         static
99         {
100                 decodingTable = new byte[128];
101
102                 for (int i = 'A'; i <= 'Z'; i++)
103                 {
104                         decodingTable[i] = (byte)(i - 'A');
105                 }
106
107                 for (int i = 'a'; i <= 'z'; i++)
108                 {
109                         decodingTable[i] = (byte)(i - 'a' + 26);
110                 }
111
112                 for (int i = '0'; i <= '9'; i++)
113                 {
114                         decodingTable[i] = (byte)(i - '0' + 52);
115                 }
116
117                 decodingTable['+'] = 62;
118                 decodingTable['/'] = 63;
119         }
120
121         /**
122          * decode the base 64 encoded input data.
123          *
124          * @return a byte array representing the decoded data.
125          */
126         public static byte[] decode(
127                 byte[]  data)
128         {
129                 byte[]  bytes;
130                 byte    b1, b2, b3, b4;
131
132                 if (data[data.length - 2] == '=')
133                 {
134                         bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
135                 }
136                 else if (data[data.length - 1] == '=')
137                 {
138                         bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
139                 }
140                 else
141                 {
142                         bytes = new byte[((data.length / 4) * 3)];
143                 }
144
145                 for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3)
146                 {
147                         b1 = decodingTable[data[i]];
148                         b2 = decodingTable[data[i + 1]];
149                         b3 = decodingTable[data[i + 2]];
150                         b4 = decodingTable[data[i + 3]];
151
152                         bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
153                         bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
154                         bytes[j + 2] = (byte)((b3 << 6) | b4);
155                 }
156
157                 if (data[data.length - 2] == '=')
158                 {
159                         b1 = decodingTable[data[data.length - 4]];
160                         b2 = decodingTable[data[data.length - 3]];
161
162                         bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
163                 }
164                 else if (data[data.length - 1] == '=')
165                 {
166                         b1 = decodingTable[data[data.length - 4]];
167                         b2 = decodingTable[data[data.length - 3]];
168                         b3 = decodingTable[data[data.length - 2]];
169
170                         bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
171                         bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
172                 }
173                 else
174                 {
175                         b1 = decodingTable[data[data.length - 4]];
176                         b2 = decodingTable[data[data.length - 3]];
177                         b3 = decodingTable[data[data.length - 2]];
178                         b4 = decodingTable[data[data.length - 1]];
179
180                         bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
181                         bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
182                         bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
183                 }
184
185                 return bytes;
186         }
187
188         /**
189          * decode the base 64 encoded String data.
190          *
191          * @return a byte array representing the decoded data.
192          */
193         public static byte[] decode(
194                 String  data)
195         {
196                 byte[]  bytes;
197                 byte    b1, b2, b3, b4;
198
199                 if (data.charAt(data.length() - 2) == '=')
200                 {
201                         bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];
202                 }
203                 else if (data.charAt(data.length() - 1) == '=')
204                 {
205                         bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];
206                 }
207                 else
208                 {
209                         bytes = new byte[((data.length() / 4) * 3)];
210                 }
211
212                 for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3)
213                 {
214                         b1 = decodingTable[data.charAt(i)];
215                         b2 = decodingTable[data.charAt(i + 1)];
216                         b3 = decodingTable[data.charAt(i + 2)];
217                         b4 = decodingTable[data.charAt(i + 3)];
218
219                         bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
220                         bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
221                         bytes[j + 2] = (byte)((b3 << 6) | b4);
222                 }
223
224                 if (data.charAt(data.length() - 2) == '=')
225                 {
226                         b1 = decodingTable[data.charAt(data.length() - 4)];
227                         b2 = decodingTable[data.charAt(data.length() - 3)];
228
229                         bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
230                 }
231                 else if (data.charAt(data.length() - 1) == '=')
232                 {
233                         b1 = decodingTable[data.charAt(data.length() - 4)];
234                         b2 = decodingTable[data.charAt(data.length() - 3)];
235                         b3 = decodingTable[data.charAt(data.length() - 2)];
236
237                         bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
238                         bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
239                 }
240                 else
241                 {
242                         b1 = decodingTable[data.charAt(data.length() - 4)];
243                         b2 = decodingTable[data.charAt(data.length() - 3)];
244                         b3 = decodingTable[data.charAt(data.length() - 2)];
245                         b4 = decodingTable[data.charAt(data.length() - 1)];
246
247                         bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
248                         bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
249                         bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
250                 }
251
252                 return bytes;
253         }
254 }