001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.jadtool;
028:
029: /**
030: * A class to do base64 encoding and decoding.
031: *
032: * Base64 is a system for representing raw byte data as Ascii
033: * characters. Each 3 input bytes will translate into 4
034: * base64 digits. Each base64 digit is represented by an Ascii
035: * character. This table shows how bytes are converted to
036: * base64 digits.
037: *
038: * base64 | | | | |
039: * digits |6 5 4 3 2 1|6 5 4 3 2 1|6 5 4 3 2 1|6 5 4 3 2 1|
040: * -------------------------------------------------
041: * input |8 7 6 5 4 3 2 1|8 7 6 5 4 3 2 1|8 7 6 5 4 3 2 1|
042: * bytes | | | |
043: *
044: * Base64 encoding always extends the input data to a multiple
045: * of 24 bits by padding with zeros.
046: *
047: * Base64 is fully described in RFC 1521.
048: * ftp://ds.internic.net/rfc/rfc1521.txt
049: *
050: *
051: * Published in "Java Cryptography", 1998 by
052: * O'Reilly & Associates.
053: *
054: */
055:
056: public class Base64 {
057: /**
058: * encode
059: *
060: * coverts a byte array to a string populated with
061: * base64 digits. It steps through the byte array
062: * calling a helper method for each block of three
063: * input bytes
064: *
065: * @param raw The byte array to encode
066: * @return A string in base64 encoding
067: */
068: public static String encode(byte[] raw) {
069: StringBuffer encoded = new StringBuffer();
070: for (int i = 0; i < raw.length; i += 3) {
071: encoded.append(encodeBlock(raw, i));
072: }
073: return encoded.toString();
074: }
075:
076: /*
077: * encodeBlock
078: *
079: * creates 4 base64 digits from three bytes of input data.
080: * we use an integer, block, to hold the 24 bits of input data.
081: *
082: * @return An array of 4 characters
083: */
084: protected static char[] encodeBlock(byte[] raw, int offset) {
085: int block = 0;
086: // how much space left in input byte array
087: int slack = raw.length - offset - 1;
088: // if there are fewer than 3 bytes in this block, calculate end
089: int end = (slack >= 2) ? 2 : slack;
090: // convert signed quantities into unsigned
091: for (int i = 0; i <= end; i++) {
092: byte b = raw[offset + i];
093: int neuter = (b < 0) ? b + 256 : b;
094: block += neuter << (8 * (2 - i));
095: }
096:
097: // extract the base64 digits, which are six bit quantities.
098: char[] base64 = new char[4];
099: for (int i = 0; i < 4; i++) {
100: int sixbit = (block >>> (6 * (3 - i))) & 0x3f;
101: base64[i] = getChar(sixbit);
102: }
103: // pad return block if needed
104: if (slack < 1)
105: base64[2] = '=';
106: if (slack < 2)
107: base64[3] = '=';
108: // always returns an array of 4 characters
109: return base64;
110: }
111:
112: /*
113: * getChar
114: *
115: * encapsulates the translation from six bit quantity
116: * to base64 digit
117: */
118: protected static char getChar(int sixBit) {
119: if (sixBit >= 0 && sixBit <= 25)
120: return (char) ('A' + sixBit);
121: if (sixBit >= 26 && sixBit <= 51)
122: return (char) ('a' + (sixBit - 26));
123: if (sixBit >= 52 && sixBit <= 61)
124: return (char) ('0' + (sixBit - 52));
125: if (sixBit == 62)
126: return '+';
127: if (sixBit == 63)
128: return '/';
129: return '?';
130: }
131:
132: /**
133: * decode
134: *
135: * convert a base64 string into an array of bytes.
136: *
137: * @param base64 A String of base64 digits to decode.
138: * @return A byte array containing the decoded value of
139: * the base64 input string
140: */
141: public static byte[] decode(String base64) {
142: // how many padding digits?
143: int pad = 0;
144: for (int i = base64.length() - 1; base64.charAt(i) == '='; i--)
145: pad++;
146: // we know know the length of the target byte array.
147: int length = base64.length() * 6 / 8 - pad;
148: byte[] raw = new byte[length];
149: int rawIndex = 0;
150: // loop through the base64 value. A correctly formed
151: // base64 string always has a multiple of 4 characters.
152: for (int i = 0; i < base64.length(); i += 4) {
153: int block = (getValue(base64.charAt(i)) << 18)
154: + (getValue(base64.charAt(i + 1)) << 12)
155: + (getValue(base64.charAt(i + 2)) << 6)
156: + (getValue(base64.charAt(i + 3)));
157: // based on the block, the byte array is filled with the
158: // appropriate 8 bit values
159: for (int j = 0; j < 3 && rawIndex + j < raw.length; j++)
160: raw[rawIndex + j] = (byte) ((block >> (8 * (2 - j))) & 0xff);
161: rawIndex += 3;
162: }
163: return raw;
164: }
165:
166: /*
167: * getValue
168: *
169: * translates from base64 digits to their 6 bit value
170: */
171: protected static int getValue(char c) {
172: if (c >= 'A' && c <= 'Z')
173: return c - 'A';
174: if (c >= 'a' && c <= 'z')
175: return c - 'a' + 26;
176: if (c >= '0' && c <= '9')
177: return c - '0' + 52;
178: if (c == '+')
179: return 62;
180: if (c == '/')
181: return 63;
182: if (c == '=')
183: return 0;
184: return -1;
185: }
186: }
|