001/* Encodes and decodes to and from Base64 notation. 002 * Copyright (C) 2003 "Eric Glass" <jcifs at samba dot org> 003 * 004 * This library is free software; you can redistribute it and/or 005 * modify it under the terms of the GNU Lesser General Public 006 * License as published by the Free Software Foundation; either 007 * version 2.1 of the License, or (at your option) any later version. 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public 015 * License along with this library; if not, write to the Free Software 016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 017 */ 018 019package net.sourceforge.spnego; 020 021public 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 final 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}