001: /*
002: * Copyright 1995-1998 by Sun Microsystems, Inc.,
003: * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
004: * All rights reserved.
005: *
006: * This software is the confidential and proprietary information
007: * of Sun Microsystems, Inc. ("Confidential Information"). You
008: * shall not disclose such Confidential Information and shall use
009: * it only in accordance with the terms of the license agreement
010: * you entered into with Sun.
011: */
012:
013: //package pa.util;
014: package com.sun.portal.cli.cert;
015:
016: import java.io.*;
017: import com.sun.portal.log.common.PortalLogger;
018: import java.util.*;
019: import java.text.*;
020:
021: /**
022: *
023: * This class encodes and decodes data to and from the Base64 format according
024: * to the specs in RFC 1521 (Section 5.2).
025: *
026: * @author Dan Crawford
027: */
028: public class Base64 {
029:
030: private static byte[] DecodeMap;
031: private static byte[] theMap = { (byte) 'A', (byte) 'B',
032: (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G',
033: (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L',
034: (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q',
035: (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V',
036: (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a',
037: (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
038: (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k',
039: (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p',
040: (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u',
041: (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z',
042: (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4',
043: (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9',
044: (byte) '+', (byte) '/' };
045:
046: //the Base64 mapping
047:
048: static {
049: DecodeMap = new byte[128];
050: for (int i = 0; i < theMap.length; i++)
051: DecodeMap[theMap[i]] = (byte) i;
052: }
053:
054: /**
055: * Convert the String into an array of bytes then send the bytes
056: through the
057: * encoding algorithim. Return the encoded data as a String object.
058: *
059: * @param theData the data that is to be Base64 encoded.
060: * @return String the base64 encoded data as a String object.
061: */
062: public static String encode(String theData) {
063:
064: if (theData == null)
065: return null;
066:
067: byte[] theBytes = theData.getBytes();
068: theData = new String(encode(theBytes));
069:
070: return theData;
071: }
072:
073: /**
074: * This is where the actual encoding takes place.
075: * returns a byte array of the encoded bytes.
076: *
077: * @param theBytes a byte array that is to be Base64 encoded.
078: * @return byte[] the Base64 encoded data.
079: */
080: public static byte[] encode(byte[] theBytes) {
081: int i = 0, place = (-1);
082: byte byte1, byte2, byte3;
083: byte[] encodedBytes = new byte[((theBytes.length + 2) / 3) * 4];
084:
085: while ((i + 2) < theBytes.length) {
086: byte1 = theBytes[i];
087: byte2 = theBytes[++i];
088: byte3 = theBytes[++i];
089:
090: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
091: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
092: + ((byte2 >>> 4) & 0xf)];
093: encodedBytes[++place] = theMap[((byte2 << 2) & 0x3c)
094: + ((byte3 >>> 6) & 0x3)];
095: encodedBytes[++place] = theMap[byte3 & 0x3F];
096: ++i;
097: }
098:
099: if ((theBytes.length - 1 - i) == 0) {
100: byte1 = theBytes[i];
101: byte2 = 0;
102: byte3 = 0;
103:
104: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
105: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
106: + ((byte2 >>> 4) & 0xf)];
107: encodedBytes[++place] = (byte) '=';
108: encodedBytes[++place] = (byte) '=';
109: }
110:
111: else if ((theBytes.length - 1 - i) == 1) {
112: byte1 = theBytes[i];
113: byte2 = theBytes[i + 1];
114: byte3 = 0;
115:
116: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
117: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
118: + ((byte2 >>> 4) & 0xf)];
119: encodedBytes[++place] = theMap[((byte2 << 2) & 0x3c)
120: + ((byte3 >>> 6) & 0x3)];
121: encodedBytes[++place] = (byte) '=';
122: }
123:
124: //add padding if necessary;
125: while ((++place) < encodedBytes.length) {
126: encodedBytes[place] = (byte) '=';
127: }
128:
129: return encodedBytes;
130: }
131:
132: /**
133: * This is where the base 64 decoding is done.
134: *
135: * @param encData the Base64 encoded data that is to be decoded.
136: * @return byte[] the decoded data.
137: */
138: public static byte[] decode(byte[] encData) {
139: if (encData == null)
140: return null;
141:
142: int tail = encData.length;
143: while (encData[tail - 1] == '=')
144: tail--;
145:
146: byte decData[] = new byte[tail - encData.length / 4];
147:
148: // ascii printable to 0-63 conversion
149: for (int idx = 0; idx < encData.length; idx++) {
150: encData[idx] = DecodeMap[encData[idx]];
151: }
152:
153: // 4-byte to 3-byte conversion
154: int sidx, didx;
155: for (sidx = 0, didx = 0; didx < decData.length - 2; sidx += 4, didx += 3) {
156: decData[didx] = (byte) (((encData[sidx] << 2) & 255) | ((encData[sidx + 1] >>> 4) & 003));
157: decData[didx + 1] = (byte) (((encData[sidx + 1] << 4) & 255) | ((encData[sidx + 2] >>> 2) & 017));
158: decData[didx + 2] = (byte) (((encData[sidx + 2] << 6) & 255) | (encData[sidx + 3] & 077));
159:
160: }
161:
162: if (didx < decData.length)
163: decData[didx] = (byte) (((encData[sidx] << 2) & 255) | ((encData[sidx + 1] >>> 4) & 003));
164: if (++didx < decData.length)
165: decData[didx] = (byte) (((encData[sidx + 1] << 4) & 255) | ((encData[sidx + 2] >>> 2) & 017));
166:
167: return decData;
168: }
169: }
|