001 package net.sourceforge.spnego;
002
003 /* Encodes and decodes to and from Base64 notation.
004 * Copyright (C) 2003 "Eric Glass" <jcifs at samba dot org>
005 *
006 * This library is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 2.1 of the License, or (at your option) any later version.
010 *
011 * This library is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with this library; if not, write to the Free Software
018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019 */
020
021 public final class Base64 {
022
023 private static final String ALPHABET =
024 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
025
026 private Base64() {
027 // default private
028 }
029
030 /**
031 * Base-64 encodes the supplied block of data. Line wrapping is not
032 * applied on output.
033 *
034 * @param bytes The block of data that is to be Base-64 encoded.
035 * @return A <code>String</code> containing the encoded data.
036 */
037 public static String encode(final byte[] bytes) {
038 int length = bytes.length;
039
040 if (length == 0) {
041 return "";
042 }
043
044 final StringBuilder buffer =
045 new StringBuilder((int) Math.ceil(length / 3d) * 4);
046 final int remainder = length % 3;
047 length -= remainder;
048 int block;
049 int idx = 0;
050 while (idx < length) {
051 block = ((bytes[idx++] & 0xff) << 16) | ((bytes[idx++] & 0xff) << 8)
052 | (bytes[idx++] & 0xff);
053 buffer.append(ALPHABET.charAt(block >>> 18));
054 buffer.append(ALPHABET.charAt((block >>> 12) & 0x3f));
055 buffer.append(ALPHABET.charAt((block >>> 6) & 0x3f));
056 buffer.append(ALPHABET.charAt(block & 0x3f));
057 }
058 if (remainder == 0) {
059 return buffer.toString();
060 }
061 if (remainder == 1) {
062 block = (bytes[idx] & 0xff) << 4;
063 buffer.append(ALPHABET.charAt(block >>> 6));
064 buffer.append(ALPHABET.charAt(block & 0x3f));
065 buffer.append("==");
066 return buffer.toString();
067 }
068 block = (((bytes[idx++] & 0xff) << 8) | ((bytes[idx]) & 0xff)) << 2;
069 buffer.append(ALPHABET.charAt(block >>> 12));
070 buffer.append(ALPHABET.charAt((block >>> 6) & 0x3f));
071 buffer.append(ALPHABET.charAt(block & 0x3f));
072 buffer.append("=");
073 return buffer.toString();
074 }
075
076 /**
077 * Decodes the supplied Base-64 encoded string.
078 *
079 * @param string The Base-64 encoded string that is to be decoded.
080 * @return A <code>byte[]</code> containing the decoded data block.
081 */
082 public static byte[] decode(final String string) {
083 final int length = string.length();
084 if (length == 0) {
085 return new byte[0];
086 }
087
088 final int pad = (string.charAt(length - 2) == '=') ? 2
089 : (string.charAt(length - 1) == '=') ? 1 : 0;
090 final int size = length * 3 / 4 - pad;
091 byte[] buffer = new byte[size];
092 int block;
093 int idx = 0;
094 int index = 0;
095 while (idx < length) {
096 block = (ALPHABET.indexOf(string.charAt(idx++)) & 0xff) << 18
097 | (ALPHABET.indexOf(string.charAt(idx++)) & 0xff) << 12
098 | (ALPHABET.indexOf(string.charAt(idx++)) & 0xff) << 6
099 | (ALPHABET.indexOf(string.charAt(idx++)) & 0xff);
100 buffer[index++] = (byte) (block >>> 16);
101 if (index < size) {
102 buffer[index++] = (byte) ((block >>> 8) & 0xff);
103 }
104 if (index < size) {
105 buffer[index++] = (byte) (block & 0xff);
106 }
107 }
108 return buffer;
109 }
110 }