From d515f0efa832cc2e89e1ea7a47d7801374016f30 Mon Sep 17 00:00:00 2001 From: brian Date: Fri, 4 Jun 2004 09:44:30 +0000 Subject: [PATCH] new base64.java - old one was buggy darcs-hash:20040604094430-24bed-18f8cbe4487a57c94a40439b7cdb5b9c7aec457c.gz --- src/org/ibex/crypto/Base64.java | 361 +++++++++++++-------------------------- 1 file changed, 114 insertions(+), 247 deletions(-) diff --git a/src/org/ibex/crypto/Base64.java b/src/org/ibex/crypto/Base64.java index f53b067..a82e44e 100644 --- a/src/org/ibex/crypto/Base64.java +++ b/src/org/ibex/crypto/Base64.java @@ -1,254 +1,121 @@ package org.ibex.crypto; -public class Base64 -{ - private static final byte[] encodingTable = - { - (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', - (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', - (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', - (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', - (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', - (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', - (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', - (byte)'v', - (byte)'w', (byte)'x', (byte)'y', (byte)'z', - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', - (byte)'7', (byte)'8', (byte)'9', - (byte)'+', (byte)'/' - }; - - /** - * encode the input data producong a base 64 encoded byte array. - * - * @return a byte array containing the base 64 encoded data. - */ - public static byte[] encode( - byte[] data) - { - byte[] bytes; - - int modulus = data.length % 3; - if (modulus == 0) - { - bytes = new byte[4 * data.length / 3]; - } - else - { - bytes = new byte[4 * ((data.length / 3) + 1)]; - } - - int dataLength = (data.length - modulus); - int a1, a2, a3; - for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) - { - a1 = data[i] & 0xff; - a2 = data[i + 1] & 0xff; - a3 = data[i + 2] & 0xff; - - bytes[j] = encodingTable[(a1 >>> 2) & 0x3f]; - bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]; - bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]; - bytes[j + 3] = encodingTable[a3 & 0x3f]; - } - - /* - * process the tail end. - */ - int b1, b2, b3; - int d1, d2; - - switch (modulus) - { - case 0: /* nothing left to do */ - break; - case 1: - d1 = data[data.length - 1] & 0xff; - b1 = (d1 >>> 2) & 0x3f; - b2 = (d1 << 4) & 0x3f; - - bytes[bytes.length - 4] = encodingTable[b1]; - bytes[bytes.length - 3] = encodingTable[b2]; - bytes[bytes.length - 2] = (byte)'='; - bytes[bytes.length - 1] = (byte)'='; - break; - case 2: - d1 = data[data.length - 2] & 0xff; - d2 = data[data.length - 1] & 0xff; - - b1 = (d1 >>> 2) & 0x3f; - b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f; - b3 = (d2 << 2) & 0x3f; - - bytes[bytes.length - 4] = encodingTable[b1]; - bytes[bytes.length - 3] = encodingTable[b2]; - bytes[bytes.length - 2] = encodingTable[b3]; - bytes[bytes.length - 1] = (byte)'='; - break; - } - - return bytes; +import java.io.UnsupportedEncodingException; + +public final class Base64 { + private Base64() { /* can't be instansiated */ } + + private static final char encodeMap[] = { + 'A','B','C','D','E','F','G','H', + 'I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X', + 'Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n', + 'o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3', + '4','5','6','7','8','9','+','/' + }; + + private static final int decodeMap[] = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, + -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1 + }; + + public static void main(String[] args){ + if(args.length == 2 && args[0].equals("encode")) + System.out.println(encode(args[1].getBytes())); + else if(args.length == 2 && args[0].equals("decode")) + System.out.println(new String(decode(args[1]))); + else { + System.out.println("Usage: Base64 {encode,decode} text"); + System.exit(1); } - - /* - * set up the decoding table. - */ - private static final byte[] decodingTable; - - static - { - decodingTable = new byte[128]; - - for (int i = 'A'; i <= 'Z'; i++) - { - decodingTable[i] = (byte)(i - 'A'); - } - - for (int i = 'a'; i <= 'z'; i++) - { - decodingTable[i] = (byte)(i - 'a' + 26); - } - - for (int i = '0'; i <= '9'; i++) - { - decodingTable[i] = (byte)(i - '0' + 52); - } - - decodingTable['+'] = 62; - decodingTable['/'] = 63; + System.exit(0); + } + + public static byte[] decode(String inString){ + char[] in = inString.toCharArray(); + int part=0; + int theBytes = 0; + byte[] out = new byte[in.length / 4 * 3]; + int outPos = 0; + for(int i=0;i>> 16) & 0xff); + out[outPos++] = (byte)((theBytes >>> 8) & 0xff); + out[outPos++] = (byte)((theBytes >>> 0) & 0xff); + } } - - /** - * decode the base 64 encoded input data. - * - * @return a byte array representing the decoded data. - */ - public static byte[] decode( - byte[] data) - { - byte[] bytes; - byte b1, b2, b3, b4; - - if (data[data.length - 2] == '=') - { - bytes = new byte[(((data.length / 4) - 1) * 3) + 1]; - } - else if (data[data.length - 1] == '=') - { - bytes = new byte[(((data.length / 4) - 1) * 3) + 2]; - } - else - { - bytes = new byte[((data.length / 4) * 3)]; - } - - for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3) - { - b1 = decodingTable[data[i]]; - b2 = decodingTable[data[i + 1]]; - b3 = decodingTable[data[i + 2]]; - b4 = decodingTable[data[i + 3]]; - - bytes[j] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2)); - bytes[j + 2] = (byte)((b3 << 6) | b4); - } - - if (data[data.length - 2] == '=') - { - b1 = decodingTable[data[data.length - 4]]; - b2 = decodingTable[data[data.length - 3]]; - - bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4)); - } - else if (data[data.length - 1] == '=') - { - b1 = decodingTable[data[data.length - 4]]; - b2 = decodingTable[data[data.length - 3]]; - b3 = decodingTable[data[data.length - 2]]; - - bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2)); - } - else - { - b1 = decodingTable[data[data.length - 4]]; - b2 = decodingTable[data[data.length - 3]]; - b3 = decodingTable[data[data.length - 2]]; - b4 = decodingTable[data[data.length - 1]]; - - bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2)); - bytes[bytes.length - 1] = (byte)((b3 << 6) | b4); - } - - return bytes; + switch(part){ + case 3: + out[outPos++] = (byte)((theBytes >>> 10) & 0xff); + out[outPos++] = (byte)((theBytes >>> 2) & 0xff); + break; + case 2: + out[outPos++] = (byte)((theBytes >> 4) & 0xff); + break; } - - /** - * decode the base 64 encoded String data. - * - * @return a byte array representing the decoded data. - */ - public static byte[] decode( - String data) - { - byte[] bytes; - byte b1, b2, b3, b4; - - if (data.charAt(data.length() - 2) == '=') - { - bytes = new byte[(((data.length() / 4) - 1) * 3) + 1]; - } - else if (data.charAt(data.length() - 1) == '=') - { - bytes = new byte[(((data.length() / 4) - 1) * 3) + 2]; - } - else - { - bytes = new byte[((data.length() / 4) * 3)]; - } - - for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3) - { - b1 = decodingTable[data.charAt(i)]; - b2 = decodingTable[data.charAt(i + 1)]; - b3 = decodingTable[data.charAt(i + 2)]; - b4 = decodingTable[data.charAt(i + 3)]; - - bytes[j] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2)); - bytes[j + 2] = (byte)((b3 << 6) | b4); - } - - if (data.charAt(data.length() - 2) == '=') - { - b1 = decodingTable[data.charAt(data.length() - 4)]; - b2 = decodingTable[data.charAt(data.length() - 3)]; - - bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4)); - } - else if (data.charAt(data.length() - 1) == '=') - { - b1 = decodingTable[data.charAt(data.length() - 4)]; - b2 = decodingTable[data.charAt(data.length() - 3)]; - b3 = decodingTable[data.charAt(data.length() - 2)]; - - bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2)); - } - else - { - b1 = decodingTable[data.charAt(data.length() - 4)]; - b2 = decodingTable[data.charAt(data.length() - 3)]; - b3 = decodingTable[data.charAt(data.length() - 2)]; - b4 = decodingTable[data.charAt(data.length() - 1)]; - - bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2)); - bytes[bytes.length - 1] = (byte)((b3 << 6) | b4); - } - - return bytes; + + if(outPos < out.length){ + byte[] a = new byte[outPos]; + System.arraycopy(out,0,a,0,outPos); + return a; + } else { + return out; + } + } + + public static String encode(String in) { return encode(getBytes(in)); } + public static String encode(byte[] in){ + int part=0; + int theBytes = 0; + char[] out = new char[(in.length / 3 + 1) * 4]; + int outPos = 0; + for(int i=0;i>> 18) & 0x3f]; + out[outPos++] = encodeMap[(theBytes >>> 12) & 0x3f]; + out[outPos++] = encodeMap[(theBytes >>> 6) & 0x3f]; + out[outPos++] = encodeMap[(theBytes >>> 0) & 0x3f]; + } + } + switch(part){ + case 2: + out[outPos++] = encodeMap[(theBytes >>> 10) & 0x3f]; + out[outPos++] = encodeMap[(theBytes >>> 4) & 0x3f]; + out[outPos++] = encodeMap[(theBytes << 2) & 0x3f]; + out[outPos++] = '='; + break; + case 1: + out[outPos++] = encodeMap[(theBytes >>> 2) & 0x3f]; + out[outPos++] = encodeMap[(theBytes << 4) & 0x3f]; + out[outPos++] = '='; + out[outPos++] = '='; + break; } + return new String(out,0,outPos); + } + + public static byte[] getBytes(String s) { + try { + return s.getBytes("US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new Error("should never happen"); + } + } } -- 1.7.10.4