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                   intintint2, a3;
43                   for (intint= 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                   intintint1, b2, b3;
59                   intint  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                  bytebytebytebyteb3, 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 (intint= 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                  bytebytebytebyteb3, 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 (intint= 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  }
255