Tagged: RFC4648

Base 64 Encoding


I just spent a whole week for a twitter xAuth client. And I had to implement Base 64 encoding by myself.

/**
 * The Base 64 Alphabet.
 *
 * '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 byte[] BASE64_ALPHABET = {
    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
    0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
    0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
    0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
    0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
    0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
    0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
};

public static String base64(final byte[] input) {

    if (input == null) {
        throw new NullPointerException("null input");
    }

    int count = input.length / 3;
    if (input.length % 3 > 0) {
        count++;
    }

    final byte[] output = new byte[count * 4];
    int index = 0;

    int pad = 0;
    int word;
    for (int i = 0; i < input.length; i += 3) {
        word = 0x00;
        for (int j = 0; j < 3; j++) {
            if ((i + j) < input.length) {
                word <<= 8;
                word |= (input[i + j] & 0xFF);
            } else {
                switch (j) {
                    case 1:
                        pad = 2;
                        word <<= 4;
                        break;
                    case 2:
                        pad = 1;
                        word <<= 2;
                        break;
                    default:
                        break;
                }
                break;
            }
        }
        for (int j = 0; j < pad; j++) {
            output[index + 3 - j] = '=';
        }
        for (int j = 3 - pad; j >= 0; j--) {
            output[index + j] = BASE64_ALPHABET[word & 0x3F];
            word >>= 6;
        }
        if (pad != 0) {
            break;
        }
        index += 4;
    }

    return new String(output);
}
Advertisements

RFC 4648 The Base16, Base32, and Base64 Data Encodings


RFC 4648 The Base16, Base32, and Base64 Data Encodings

name bits/char bytes/word chars/word pad notes
base16 (hex) 4 1 2 N/A
base32 5 5 8 YES
base32hex 5 5 8 YES
base64 6 3 4 YES
base64url 6 3 4 NO

Base.java
Base16.java
Base32.java
Base32Hex.java
Base64.java
Base64Url.java

import java.io.IOException;
import java.util.Arrays;

import jinahya.rfc4648.*;

public class Test {

    private static final PrintStream UTF8;

    static {
        try {
            UTF8 = new PrintStream(System.out, true, "UTF-8");
        } catch (UnsupportedEncodingException uee) {
            throw new InstantiationError(
                "What can I do to make you love me?");
        }
    }
    private static final String[] WELCOMES = {
        "Salaam", "Dobrodošli", "歡迎", "欢迎", "歡迎",
        "Vítáme tĕ", "Velkommen", "Welkom", "Bienvenue", "Wolkom",
        "Willkommen", "Καλώς ορίσατε", "Aloha", "Shalom", "Benvenuto",
        "ようこそ", "환영합니다", "Тавтай морилогтун", "Bem-vindo",
        "Bem-vinda", "Bienvenido", "Välkommen", "Mabuhay", "Swaagatham",
        "Suswaagatham", "Merhaba"};

    public static void main(String[] args) throws IOException {
        if (args.length == 0) {
            test(WELCOMES);
        } else {
            test(args);
        }
    }

    private static void test(final String[] strings) throws IOException {
        for (String string : strings) {
            System.out.printf("%1$5s: %2$s\n", "input", string);
            final byte[] original = string.getBytes("UTF-8");
            System.out.printf("%1$5s: ", "UTF-8");
            for (byte b : original) {
                System.out.printf("%1$s", Integer.toHexString(b & 0xFF));
            }
            System.out.printf("\n");
            test("base64", new Base64(), original);
            test("base64url", new Base64URL(), original);
            test("base32", new Base32(), original);
            test("base32hex", new Base32HEX(), original);
            test("base16", new Base16(), original);
        }
    }

    private static void test(final String name, final Base base,
                             final byte[] original)
        throws IOException {
        final char[] encoded = base.encode(original);
        System.out.printf("\t%1$10s: %2$s\n", name, new String(encoded));
        final byte[] decoded = base.decode(encoded);
        assert Arrays.equals(decoded, original) : "fail";
    }
}
input: Salaam
UTF-8: 53616c61616d
	    base64: U2FsYWFt
	 base64url: U2FsYWFt
	    base32: KNQWYYLBNU======
	 base32hex: ADGMOOB1DK======
	    base16: 53616C61616D
input: Dobrodošli
UTF-8: 446f62726f646fc5a16c69
	    base64: RG9icm9kb8WhbGk=
	 base64url: RG9icm9kb8WhbGk
	    base32: IRXWE4TPMRX4LILMNE======
	 base32hex: 8HNM4SJFCHNSB8BCD4======
	    base16: 446F62726F646FC5A16C69
input: 歡迎
UTF-8: e6ada1e8bf8e
	    base64: 5q2h6L+O
	 base64url: 5q2h6L-O
	    base32: 42W2D2F7RY======
	 base32hex: SQMQ3Q5VHO======
	    base16: E6ADA1E8BF8E
input: 欢迎
UTF-8: e6aca2e8bf8e
	    base64: 5qyi6L+O
	 base64url: 5qyi6L-O
	    base32: 42WKF2F7RY======
	 base32hex: SQMA5Q5VHO======
	    base16: E6ACA2E8BF8E
input: 歡迎
UTF-8: e6ada1e8bf8e
	    base64: 5q2h6L+O
	 base64url: 5q2h6L-O
	    base32: 42W2D2F7RY======
	 base32hex: SQMQ3Q5VHO======
	    base16: E6ADA1E8BF8E
input: Vítáme tĕ
UTF-8: 56c3ad74c3a16d652074c495
	    base64: VsOtdMOhbWUgdMSV
	 base64url: VsOtdMOhbWUgdMSV
	    base32: K3B225GDUFWWKIDUYSKQ====
	 base32hex: AR1QQT63K5MMA83KOIAG====
	    base16: 56C3AD74C3A16D652074C495
input: Velkommen
UTF-8: 56656c6b6f6d6d656e
	    base64: VmVsa29tbWVu
	 base64url: VmVsa29tbWVu
	    base32: KZSWY23PNVWWK3Q=
	 base32hex: APIMOQRFDLMMARG=
	    base16: 56656C6B6F6D6D656E
input: Welkom
UTF-8: 57656c6b6f6d
	    base64: V2Vsa29t
	 base64url: V2Vsa29t
	    base32: K5SWY23PNU======
	 base32hex: ATIMOQRFDK======
	    base16: 57656C6B6F6D
input: Bienvenue
UTF-8: 4269656e76656e7565
	    base64: QmllbnZlbnVl
	 base64url: QmllbnZlbnVl
	    base32: IJUWK3TWMVXHKZI=
	 base32hex: 89KMARJMCLN7AP8=
	    base16: 4269656E76656E7565
input: Wolkom
UTF-8: 576f6c6b6f6d
	    base64: V29sa29t
	 base64url: V29sa29t
	    base32: K5XWY23PNU======
	 base32hex: ATNMOQRFDK======
	    base16: 576F6C6B6F6D
input: Willkommen
UTF-8: 57696c6c6b6f6d6d656e
	    base64: V2lsbGtvbW1lbg==
	 base64url: V2lsbGtvbW1lbg
	    base32: K5UWY3DLN5WW2ZLO
	 base32hex: ATKMOR3BDTMMQPBE
	    base16: 57696C6C6B6F6D6D656E
input: Καλώς ορίσατε
UTF-8: ce9aceb1cebbcf8ecf8220cebfcf81ceafcf83ceb1cf84ceb5
	    base64: zprOsc67z47PgiDOv8+Bzq/Pg86xz4TOtQ==
	 base64url: zprOsc67z47PgiDOv8-Bzq_Pg86xz4TOtQ
	    base32: Z2NM5MOOXPHY5T4CEDHL7T4BZ2X47A6OWHHYJTVV
	 base32hex: PQDCTCEENF7OTJS2437BVJS1PQNSV0UEM77O9JLL
	    base16: CE9ACEB1CEBBCF8ECF8220CEBFCF81CEAFCF83CEB1CF84CEB5
input: Aloha
UTF-8: 416c6f6861
	    base64: QWxvaGE=
	 base64url: QWxvaGE
	    base32: IFWG62DB
	 base32hex: 85M6UQ31
	    base16: 416C6F6861
input: Shalom
UTF-8: 5368616c6f6d
	    base64: U2hhbG9t
	 base64url: U2hhbG9t
	    base32: KNUGC3DPNU======
	 base32hex: ADK62R3FDK======
	    base16: 5368616C6F6D
input: Benvenuto
UTF-8: 42656e76656e75746f
	    base64: QmVudmVudXRv
	 base64url: QmVudmVudXRv
	    base32: IJSW45TFNZ2XI3Y=
	 base32hex: 89IMSTJ5DPQN8RO=
	    base16: 42656E76656E75746F
input: ようこそ
UTF-8: e38288e38186e38193e3819d
	    base64: 44KI44GG44GT44Gd
	 base64url: 44KI44GG44GT44Gd
	    base32: 4OBIRY4BQ3RYDE7DQGOQ====
	 base32hex: SE18HOS1GRHO34V3G6EG====
	    base16: E38288E38186E38193E3819D
input: 환영합니다
UTF-8: ed9998ec9881ed95a9eb8b88eb8ba4
	    base64: 7ZmY7JiB7ZWp64uI64uk
	 base64url: 7ZmY7JiB7ZWp64uI64uk
	    base32: 5WMZR3EYQHWZLKPLROEOXC5E
	 base32hex: TMCPHR4OG7MPBAFBHE4EN2T4
	    base16: ED9998EC9881ED95A9EB8B88EB8BA4
input: Тавтай морилогтун
UTF-8: d0a2d0b0d0b2d182d0b0d0b920d0bcd0bed180d0b8d0bbd0bed0b3d182d183d0bd
	    base64: 0KLQsNCy0YLQsNC5INC80L7RgNC40LvQvtCz0YLRg9C9
	 base64url: 0KLQsNCy0YLQsNC5INC80L7RgNC40LvQvtCz0YLRg9C9
	    base32: 2CRNBMGQWLIYFUFQ2C4SBUF42C7NDAGQXDILXUF62CZ5DAWRQPIL2===
	 base32hex: Q2HD1C6GMB8O5K5GQ2SI1K5SQ2VD306GN38BNK5UQ2PT30MHGF8BQ===
	    base16: D0A2D0B0D0B2D182D0B0D0B920D0BCD0BED180D0B8D0BBD0BED0B3D182D183D0BD
input: Bem-vindo
UTF-8: 42656d2d76696e646f
	    base64: QmVtLXZpbmRv
	 base64url: QmVtLXZpbmRv
	    base32: IJSW2LLWNFXGI3Y=
	 base32hex: 89IMQBBMD5N68RO=
	    base16: 42656D2D76696E646F
input: Bem-vinda
UTF-8: 42656d2d76696e6461
	    base64: QmVtLXZpbmRh
	 base64url: QmVtLXZpbmRh
	    base32: IJSW2LLWNFXGIYI=
	 base32hex: 89IMQBBMD5N68O8=
	    base16: 42656D2D76696E6461
input: Bienvenido
UTF-8: 4269656e76656e69646f
	    base64: QmllbnZlbmlkbw==
	 base64url: QmllbnZlbmlkbw
	    base32: IJUWK3TWMVXGSZDP
	 base32hex: 89KMARJMCLN6IP3F
	    base16: 4269656E76656E69646F
input: Välkommen
UTF-8: 56c3a46c6b6f6d6d656e
	    base64: VsOkbGtvbW1lbg==
	 base64url: VsOkbGtvbW1lbg
	    base32: K3B2I3DLN5WW2ZLO
	 base32hex: AR1Q8R3BDTMMQPBE
	    base16: 56C3A46C6B6F6D6D656E
input: Mabuhay
UTF-8: 4d616275686179
	    base64: TWFidWhheQ==
	 base64url: TWFidWhheQ
	    base32: JVQWE5LIMF4Q====
	 base32hex: 9LGM4TB8C5SG====
	    base16: 4D616275686179
input: Swaagatham
UTF-8: 5377616167617468616d
	    base64: U3dhYWdhdGhhbQ==
	 base64url: U3dhYWdhdGhhbQ
	    base32: KN3WCYLHMF2GQYLN
	 base32hex: ADRM2OB7C5Q6GOBD
	    base16: 5377616167617468616D
input: Suswaagatham
UTF-8: 53757377616167617468616d
	    base64: U3Vzd2FhZ2F0aGFt
	 base64url: U3Vzd2FhZ2F0aGFt
	    base32: KN2XG53BMFTWC5DIMFWQ====
	 base32hex: ADQN6TR1C5JM2T38C5MG====
	    base16: 53757377616167617468616D
input: Merhaba
UTF-8: 4d657268616261
	    base64: TWVyaGFiYQ==
	 base64url: TWVyaGFiYQ
	    base32: JVSXE2DBMJQQ====
	 base32hex: 9LIN4Q31C9GG====
	    base16: 4D657268616261