KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > maverick > crypto > encoders > Base64


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.maverick.crypto.encoders;
21
22 import java.io.ByteArrayOutputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.OutputStream JavaDoc;
25
26 public class Base64
27 {
28     private static final byte[] encodingTable =
29         {
30             (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
31             (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
32             (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
33             (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
34             (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
35             (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
36             (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
37             (byte)'v',
38             (byte)'w', (byte)'x', (byte)'y', (byte)'z',
39             (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
40             (byte)'7', (byte)'8', (byte)'9',
41             (byte)'+', (byte)'/'
42         };
43
44     /**
45      * encode the input data producing a base 64 encoded byte array.
46      *
47      * @return a byte array containing the base 64 encoded data.
48      */

49     public static byte[] encode(
50         byte[] data)
51     {
52         byte[] bytes;
53
54         int modulus = data.length % 3;
55         if (modulus == 0)
56         {
57             bytes = new byte[4 * data.length / 3];
58         }
59         else
60         {
61             bytes = new byte[4 * ((data.length / 3) + 1)];
62         }
63
64         int dataLength = (data.length - modulus);
65         int a1, a2, a3;
66         for (int i = 0, j = 0; i < dataLength; i += 3, j += 4)
67         {
68             a1 = data[i] & 0xff;
69             a2 = data[i + 1] & 0xff;
70             a3 = data[i + 2] & 0xff;
71
72             bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
73             bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
74             bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
75             bytes[j + 3] = encodingTable[a3 & 0x3f];
76         }
77
78         /*
79          * process the tail end.
80          */

81         int b1, b2, b3;
82         int d1, d2;
83
84         switch (modulus)
85         {
86         case 0: /* nothing left to do */
87             break;
88         case 1:
89             d1 = data[data.length - 1] & 0xff;
90             b1 = (d1 >>> 2) & 0x3f;
91             b2 = (d1 << 4) & 0x3f;
92
93             bytes[bytes.length - 4] = encodingTable[b1];
94             bytes[bytes.length - 3] = encodingTable[b2];
95             bytes[bytes.length - 2] = (byte)'=';
96             bytes[bytes.length - 1] = (byte)'=';
97             break;
98         case 2:
99             d1 = data[data.length - 2] & 0xff;
100             d2 = data[data.length - 1] & 0xff;
101
102             b1 = (d1 >>> 2) & 0x3f;
103             b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
104             b3 = (d2 << 2) & 0x3f;
105
106             bytes[bytes.length - 4] = encodingTable[b1];
107             bytes[bytes.length - 3] = encodingTable[b2];
108             bytes[bytes.length - 2] = encodingTable[b3];
109             bytes[bytes.length - 1] = (byte)'=';
110             break;
111         }
112
113         return bytes;
114     }
115
116     /*
117      * set up the decoding table.
118      */

119     private static final byte[] decodingTable;
120
121     static
122     {
123         decodingTable = new byte[128];
124
125         for (int i = 'A'; i <= 'Z'; i++)
126         {
127             decodingTable[i] = (byte)(i - 'A');
128         }
129
130         for (int i = 'a'; i <= 'z'; i++)
131         {
132             decodingTable[i] = (byte)(i - 'a' + 26);
133         }
134
135         for (int i = '0'; i <= '9'; i++)
136         {
137             decodingTable[i] = (byte)(i - '0' + 52);
138         }
139
140         decodingTable['+'] = 62;
141         decodingTable['/'] = 63;
142     }
143
144     /**
145      * decode the base 64 encoded input data. It is assumed the input data is valid.
146      *
147      * @return a byte array representing the decoded data.
148      */

149     public static byte[] decode(
150         byte[] data)
151     {
152         byte[] bytes;
153         byte b1, b2, b3, b4;
154
155         if (data[data.length - 2] == '=')
156         {
157             bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
158         }
159         else if (data[data.length - 1] == '=')
160         {
161             bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
162         }
163         else
164         {
165             bytes = new byte[((data.length / 4) * 3)];
166         }
167
168         for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3)
169         {
170             b1 = decodingTable[data[i]];
171             b2 = decodingTable[data[i + 1]];
172             b3 = decodingTable[data[i + 2]];
173             b4 = decodingTable[data[i + 3]];
174
175             bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
176             bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
177             bytes[j + 2] = (byte)((b3 << 6) | b4);
178         }
179
180         if (data[data.length - 2] == '=')
181         {
182             b1 = decodingTable[data[data.length - 4]];
183             b2 = decodingTable[data[data.length - 3]];
184
185             bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
186         }
187         else if (data[data.length - 1] == '=')
188         {
189             b1 = decodingTable[data[data.length - 4]];
190             b2 = decodingTable[data[data.length - 3]];
191             b3 = decodingTable[data[data.length - 2]];
192
193             bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
194             bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
195         }
196         else
197         {
198             b1 = decodingTable[data[data.length - 4]];
199             b2 = decodingTable[data[data.length - 3]];
200             b3 = decodingTable[data[data.length - 2]];
201             b4 = decodingTable[data[data.length - 1]];
202
203             bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
204             bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
205             bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
206         }
207
208         return bytes;
209     }
210
211     private static boolean ignore(
212         char c)
213     {
214         return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
215     }
216
217     /**
218      * decode the base 64 encoded String data - whitespace will be ignored.
219      *
220      * @return a byte array representing the decoded data.
221      */

222     public static byte[] decode(
223         String JavaDoc data)
224     {
225         ByteArrayOutputStream JavaDoc bOut = new ByteArrayOutputStream JavaDoc();
226
227         try
228         {
229             decode(data, bOut);
230         }
231         catch (IOException JavaDoc e)
232         {
233             throw new RuntimeException JavaDoc("exception decoding base64 string: " + e);
234         }
235
236         return bOut.toByteArray();
237     }
238
239     /**
240      * decode the base 64 encoded String data writing it to the given output stream,
241      * whitespace characters will be ignored.
242      *
243      * @return the number of bytes produced.
244      */

245     public static int decode(
246         String JavaDoc data,
247         OutputStream JavaDoc out)
248         throws IOException JavaDoc
249     {
250         byte[] bytes;
251         byte b1, b2, b3, b4;
252         int length = 0;
253
254         int end = data.length();
255
256         while (end > 0)
257         {
258             if (!ignore(data.charAt(end - 1)))
259             {
260                 break;
261             }
262
263             end--;
264         }
265
266         for (int i = 0; i < end - 4; i += 4)
267         {
268             if (ignore(data.charAt(i)))
269             {
270                 continue;
271             }
272
273             b1 = decodingTable[data.charAt(i)];
274             b2 = decodingTable[data.charAt(i + 1)];
275             b3 = decodingTable[data.charAt(i + 2)];
276             b4 = decodingTable[data.charAt(i + 3)];
277
278             out.write((b1 << 2) | (b2 >> 4));
279             out.write((b2 << 4) | (b3 >> 2));
280             out.write((b3 << 6) | b4);
281
282             length += 3;
283         }
284
285         if (data.charAt(end - 2) == '=')
286         {
287             b1 = decodingTable[data.charAt(end - 4)];
288             b2 = decodingTable[data.charAt(end - 3)];
289
290             out.write((b1 << 2) | (b2 >> 4));
291
292             length += 1;
293         }
294         else if (data.charAt(end - 1) == '=')
295         {
296             b1 = decodingTable[data.charAt(end - 4)];
297             b2 = decodingTable[data.charAt(end - 3)];
298             b3 = decodingTable[data.charAt(end - 2)];
299
300             out.write((b1 << 2) | (b2 >> 4));
301             out.write((b2 << 4) | (b3 >> 2));
302
303             length += 2;
304         }
305         else
306         {
307             b1 = decodingTable[data.charAt(end - 4)];
308             b2 = decodingTable[data.charAt(end - 3)];
309             b3 = decodingTable[data.charAt(end - 2)];
310             b4 = decodingTable[data.charAt(end - 1)];
311
312             out.write((b1 << 2) | (b2 >> 4));
313             out.write((b2 << 4) | (b3 >> 2));
314             out.write((b3 << 6) | b4);
315
316             length += 3;
317         }
318
319         return length;
320     }
321 }
322
Popular Tags