1526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen/* 2526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Copyright (C) 2007 Esmertec AG. 3526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Copyright (C) 2007 The Android Open Source Project 4526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * 5526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Licensed under the Apache License, Version 2.0 (the "License"); 6526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * you may not use this file except in compliance with the License. 7526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * You may obtain a copy of the License at 8526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * 9526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * http://www.apache.org/licenses/LICENSE-2.0 10526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * 11526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Unless required by applicable law or agreed to in writing, software 12526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * distributed under the License is distributed on an "AS IS" BASIS, 13526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * See the License for the specific language governing permissions and 15526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * limitations under the License. 16526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */ 17526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 18526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenpackage com.google.android.mms.pdu; 19526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 20526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenpublic class Base64 { 21526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen /** 22526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Used to get the number of Quadruples. 23526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */ 24526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen static final int FOURBYTE = 4; 25526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 26526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen /** 27526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Byte used to pad output. 28526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */ 29526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen static final byte PAD = (byte) '='; 30526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 31526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen /** 32526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * The base length. 33526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */ 34526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen static final int BASELENGTH = 255; 35526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 36526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen // Create arrays to hold the base64 characters 37526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen private static byte[] base64Alphabet = new byte[BASELENGTH]; 38526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 39526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen // Populating the character arrays 40526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen static { 41526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen for (int i = 0; i < BASELENGTH; i++) { 42526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen base64Alphabet[i] = (byte) -1; 43526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 44526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen for (int i = 'Z'; i >= 'A'; i--) { 45526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen base64Alphabet[i] = (byte) (i - 'A'); 46526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 47526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen for (int i = 'z'; i >= 'a'; i--) { 48526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen base64Alphabet[i] = (byte) (i - 'a' + 26); 49526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 50526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen for (int i = '9'; i >= '0'; i--) { 51526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen base64Alphabet[i] = (byte) (i - '0' + 52); 52526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 53526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 54526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen base64Alphabet['+'] = 62; 55526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen base64Alphabet['/'] = 63; 56526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 57526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 58526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen /** 59526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Decodes Base64 data into octects 60526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * 61526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * @param base64Data Byte array containing Base64 data 62526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * @return Array containing decoded data. 63526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */ 64526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen public static byte[] decodeBase64(byte[] base64Data) { 65526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen // RFC 2045 requires that we discard ALL non-Base64 characters 66526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen base64Data = discardNonBase64(base64Data); 67526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 68526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen // handle the edge case, so we don't have to worry about it later 69526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen if (base64Data.length == 0) { 70526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen return new byte[0]; 71526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 72526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 73526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen int numberQuadruple = base64Data.length / FOURBYTE; 74526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen byte decodedData[] = null; 75526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0; 76526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 77526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen // Throw away anything not in base64Data 78526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 79526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen int encodedIndex = 0; 80526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen int dataIndex = 0; 81526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen { 82526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen // this sizes the output array properly - rlw 83526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen int lastData = base64Data.length; 84526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen // ignore the '=' padding 85526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen while (base64Data[lastData - 1] == PAD) { 86526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen if (--lastData == 0) { 87526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen return new byte[0]; 88526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 89526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 90526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen decodedData = new byte[lastData - numberQuadruple]; 91526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 92526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 93526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen for (int i = 0; i < numberQuadruple; i++) { 94526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen dataIndex = i * 4; 95526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen marker0 = base64Data[dataIndex + 2]; 96526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen marker1 = base64Data[dataIndex + 3]; 97526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 98526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen b1 = base64Alphabet[base64Data[dataIndex]]; 99526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen b2 = base64Alphabet[base64Data[dataIndex + 1]]; 100526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 101526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen if (marker0 != PAD && marker1 != PAD) { 102526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen //No PAD e.g 3cQl 103526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen b3 = base64Alphabet[marker0]; 104526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen b4 = base64Alphabet[marker1]; 105526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 106526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); 107526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen decodedData[encodedIndex + 1] = 108526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); 109526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4); 110526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } else if (marker0 == PAD) { 111526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen //Two PAD e.g. 3c[Pad][Pad] 112526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); 113526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } else if (marker1 == PAD) { 114526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen //One PAD e.g. 3cQ[Pad] 115526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen b3 = base64Alphabet[marker0]; 116526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 117526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); 118526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen decodedData[encodedIndex + 1] = 119526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); 120526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 121526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen encodedIndex += 3; 122526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 123526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen return decodedData; 124526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 125526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 126526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen /** 127526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Check octect wheter it is a base64 encoding. 128526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * 129526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * @param octect to be checked byte 130526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * @return ture if it is base64 encoding, false otherwise. 131526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */ 132526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen private static boolean isBase64(byte octect) { 133526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen if (octect == PAD) { 134526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen return true; 135526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } else if (base64Alphabet[octect] == -1) { 136526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen return false; 137526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } else { 138526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen return true; 139526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 140526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 141526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 142526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen /** 143526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Discards any characters outside of the base64 alphabet, per 144526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * the requirements on page 25 of RFC 2045 - "Any characters 145526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * outside of the base64 alphabet are to be ignored in base64 146526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * encoded data." 147526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * 148526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * @param data The base-64 encoded data to groom 149526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * @return The data, less non-base64 characters (see RFC 2045). 150526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */ 151526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen static byte[] discardNonBase64(byte[] data) { 152526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen byte groomedData[] = new byte[data.length]; 153526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen int bytesCopied = 0; 154526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 155526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen for (int i = 0; i < data.length; i++) { 156526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen if (isBase64(data[i])) { 157526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen groomedData[bytesCopied++] = data[i]; 158526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 159526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 160526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 161526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen byte packedData[] = new byte[bytesCopied]; 162526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 163526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); 164526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 165526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen return packedData; 166526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 167526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen} 168