1 /* 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.messaging.saaj.util; 27 28 29 // Cut & paste from tomcat 30 31 /** 32 * This class provides encode/decode for RFC 2045 Base64 as 33 * defined by RFC 2045, N. Freed and N. Borenstein. 34 * RFC 2045: Multipurpose Internet Mail Extensions (MIME) 35 * Part One: Format of Internet Message Bodies. Reference 36 * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt 37 * This class is used by XML Schema binary format validation 38 * 39 * @author Jeffrey Rodriguez 40 */ 41 public final class Base64 { 42 43 44 static private final int BASELENGTH = 255; 45 static private final int LOOKUPLENGTH = 63; 46 static private final int TWENTYFOURBITGROUP = 24; 47 static private final int EIGHTBIT = 8; 48 static private final int SIXTEENBIT = 16; 49 static private final int FOURBYTE = 4; 50 51 52 static private final byte PAD = ( byte ) '='; 53 static private byte [] base64Alphabet = new byte[BASELENGTH]; 54 static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; 55 56 static { 57 58 for (int i = 0; i<BASELENGTH; i++ ) { 59 base64Alphabet[i] = -1; 60 } 61 for ( int i = 'Z'; i >= 'A'; i-- ) { 62 base64Alphabet[i] = (byte) (i-'A'); 63 } 64 for ( int i = 'z'; i>= 'a'; i--) { 65 base64Alphabet[i] = (byte) ( i-'a' + 26); 66 } 67 68 for ( int i = '9'; i >= '0'; i--) { 69 base64Alphabet[i] = (byte) (i-'0' + 52); 70 } 71 72 base64Alphabet['+'] = 62; 73 base64Alphabet['/'] = 63; 74 75 for (int i = 0; i<=25; i++ ) 76 lookUpBase64Alphabet[i] = (byte) ('A'+i ); 77 78 for (int i = 26, j = 0; i<=51; i++, j++ ) 79 lookUpBase64Alphabet[i] = (byte) ('a'+ j ); 80 81 for (int i = 52, j = 0; i<=61; i++, j++ ) 82 lookUpBase64Alphabet[i] = (byte) ('0' + j ); 83 84 } 85 86 87 static boolean isBase64( byte octect ) { 88 //shall we ignore white space? JEFF?? 89 return(octect == PAD || base64Alphabet[octect] != -1 ); 90 } 91 92 93 static boolean isArrayByteBase64( byte[] arrayOctect ) { 94 int length = arrayOctect.length; 95 if ( length == 0 ) 96 return false; 97 for ( int i=0; i < length; i++ ) { 98 if ( Base64.isBase64( arrayOctect[i] ) == false) 99 return false; 100 } 101 return true; 102 } 103 104 /** 105 * Encodes hex octects into Base64 106 * 107 * @param binaryData Array containing binaryData 108 * @return Encoded Base64 array 109 */ 110 public static byte[] encode( byte[] binaryData ) { 111 int lengthDataBits = binaryData.length*EIGHTBIT; 112 int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; 113 int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; 114 byte encodedData[] = null; 115 116 117 if ( fewerThan24bits != 0 ) //data not divisible by 24 bit 118 encodedData = new byte[ (numberTriplets + 1 )*4 ]; 119 else // 16 or 8 bit 120 encodedData = new byte[ numberTriplets*4 ]; 121 122 byte k=0, l=0, b1=0,b2=0,b3=0; 123 124 int encodedIndex = 0; 125 int dataIndex = 0; 126 int i = 0; 127 for ( i = 0; i<numberTriplets; i++ ) { 128 129 dataIndex = i*3; 130 b1 = binaryData[dataIndex]; 131 b2 = binaryData[dataIndex + 1]; 132 b3 = binaryData[dataIndex + 2]; 133 134 l = (byte)(b2 & 0x0f); 135 k = (byte)(b1 & 0x03); 136 137 encodedIndex = i*4; 138 encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; 139 encodedData[encodedIndex+1] = lookUpBase64Alphabet[(b2 >>4 ) | 140 ( k<<4 )]; 141 encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | 142 ( b3>>6)]; 143 encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ]; 144 } 145 146 // form integral number of 6-bit groups 147 dataIndex = i*3; 148 encodedIndex = i*4; 149 if (fewerThan24bits == EIGHTBIT ) { 150 b1 = binaryData[dataIndex]; 151 k = (byte) ( b1 &0x03 ); 152 encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; 153 encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; 154 encodedData[encodedIndex + 2] = PAD; 155 encodedData[encodedIndex + 3] = PAD; 156 } else if ( fewerThan24bits == SIXTEENBIT ) { 157 158 b1 = binaryData[dataIndex]; 159 b2 = binaryData[dataIndex +1 ]; 160 l = ( byte ) ( b2 &0x0f ); 161 k = ( byte ) ( b1 &0x03 ); 162 encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; 163 encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ (b2 >>4 ) 164 | ( k<<4 )]; 165 encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; 166 encodedData[encodedIndex + 3] = PAD; 167 } 168 return encodedData; 169 } 170 171 172 /** 173 * Decodes Base64 data into octects 174 * 175 * @param base64Data Byte array containing Base64 data 176 * @return Array containind decoded data. 177 */ 178 public byte[] decode( byte[] base64Data ) { 179 int numberQuadruple = base64Data.length/FOURBYTE; 180 byte decodedData[] = null; 181 byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0; 182 183 // Throw away anything not in base64Data 184 // Adjust size 185 186 int encodedIndex = 0; 187 int dataIndex = 0; 188 decodedData = new byte[ numberQuadruple*3 + 1 ]; 189 190 for (int i = 0; i<numberQuadruple; i++ ) { 191 dataIndex = i*4; 192 marker0 = base64Data[dataIndex +2]; 193 marker1 = base64Data[dataIndex +3]; 194 195 b1 = base64Alphabet[base64Data[dataIndex]]; 196 b2 = base64Alphabet[base64Data[dataIndex +1]]; 197 198 if ( marker0 != PAD && marker1 != PAD ) { //No PAD e.g 3cQl 199 b3 = base64Alphabet[ marker0 ]; 200 b4 = base64Alphabet[ marker1 ]; 201 202 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; 203 decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( 204 (b3>>2) & 0xf) ); 205 decodedData[encodedIndex+2] = (byte)( b3<<6 | b4 ); 206 } else if ( marker0 == PAD ) { //Two PAD e.g. 3c[Pad][Pad] 207 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; 208 decodedData[encodedIndex+1] = (byte)((b2 & 0xf)<<4 ); 209 decodedData[encodedIndex+2] = (byte) 0; 210 } else if ( marker1 == PAD ) { //One PAD e.g. 3cQ[Pad] 211 b3 = base64Alphabet[ marker0 ]; 212 213 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ); 214 decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( 215 (b3>>2) & 0xf) ); 216 decodedData[encodedIndex+2] = (byte)( b3<<6); 217 } 218 encodedIndex += 3; 219 } 220 return decodedData; 221 222 } 223 224 static final int base64[]= { 225 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 226 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 227 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 228 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 229 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 230 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 231 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 232 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 233 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 234 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 235 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 236 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 237 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 238 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 239 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 240 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 241 }; 242 243 public static String base64Decode( String orig ) { 244 char chars[]=orig.toCharArray(); 245 StringBuilder sb=new StringBuilder(); 246 int i=0; 247 248 int shift = 0; // # of excess bits stored in accum 249 int acc = 0; 250 251 for (i=0; i<chars.length; i++) { 252 int v = base64[ chars[i] & 0xFF ]; 253 254 if ( v >= 64 ) { 255 if( chars[i] != '=' ) 256 System.out.println("Wrong char in base64: " + chars[i]); 257 } else { 258 acc= ( acc << 6 ) | v; 259 shift += 6; 260 if ( shift >= 8 ) { 261 shift -= 8; 262 sb.append( (char) ((acc >> shift) & 0xff)); 263 } 264 } 265 } 266 return sb.toString(); 267 } 268 269 270 }