Importing Handle Service code.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / common / Base64.java
1 package edu.internet2.middleware.shibboleth.common;
2
3 /**
4  * The Bouncy Castle License
5  *
6  * Copyright (c) 2000 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
7  * <p>
8  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
9  * and associated documentation files (the "Software"), to deal in the Software without restriction, 
10  * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
11  * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  * <p>
14  * The above copyright notice and this permission notice shall be included in all copies or substantial
15  * portions of the Software.
16  * <p>
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
19  * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
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 producong 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.
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         /**
212          * decode the base 64 encoded String data.
213          *
214          * @return a byte array representing the decoded data.
215          */
216         public static byte[] decode(
217                 String  data)
218         {
219                 byte[]  bytes;
220                 byte    b1, b2, b3, b4;
221
222                 if (data.charAt(data.length() - 2) == '=')
223                 {
224                         bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];
225                 }
226                 else if (data.charAt(data.length() - 1) == '=')
227                 {
228                         bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];
229                 }
230                 else
231                 {
232                         bytes = new byte[((data.length() / 4) * 3)];
233                 }
234
235                 for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3)
236                 {
237                         b1 = decodingTable[data.charAt(i)];
238                         b2 = decodingTable[data.charAt(i + 1)];
239                         b3 = decodingTable[data.charAt(i + 2)];
240                         b4 = decodingTable[data.charAt(i + 3)];
241
242                         bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
243                         bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
244                         bytes[j + 2] = (byte)((b3 << 6) | b4);
245                 }
246
247                 if (data.charAt(data.length() - 2) == '=')
248                 {
249                         b1 = decodingTable[data.charAt(data.length() - 4)];
250                         b2 = decodingTable[data.charAt(data.length() - 3)];
251
252                         bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
253                 }
254                 else if (data.charAt(data.length() - 1) == '=')
255                 {
256                         b1 = decodingTable[data.charAt(data.length() - 4)];
257                         b2 = decodingTable[data.charAt(data.length() - 3)];
258                         b3 = decodingTable[data.charAt(data.length() - 2)];
259
260                         bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
261                         bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
262                 }
263                 else
264                 {
265                         b1 = decodingTable[data.charAt(data.length() - 4)];
266                         b2 = decodingTable[data.charAt(data.length() - 3)];
267                         b3 = decodingTable[data.charAt(data.length() - 2)];
268                         b4 = decodingTable[data.charAt(data.length() - 1)];
269
270                         bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
271                         bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
272                         bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
273                 }
274
275                 return bytes;
276         }
277 }