Sorcerer's IsleCode cfPassphrase / files

     1// Copyright (C) 2011 - Will Glozer.  All rights reserved.
     2
     3package com.lambdaworks.codec;
     4
     5import java.util.Arrays;
     6
     7/**
     8 * High-performance base64 codec based on the algorithm used in Mikael Grev's MiG Base64.
     9 * This implementation is designed to handle base64 without line splitting and with
    10 * optional padding. Alternative character tables may be supplied to the {@code encode}
    11 * and {@code decode} methods to implement modified base64 schemes.
    12 *
    13 * Decoding assumes correct input, the caller is responsible for ensuring that the input
    14 * contains no invalid characters.
    15 *
    16 * @author Will Glozer
    17 */
    18public class Base64 {
    19    private static final char[] encode = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
    20    private static final int[]  decode = new int[128];
    21    private static final char   pad    = '=';
    22
    23    static {
    24        Arrays.fill(decode, -1);
    25        for (int i = 0; i < encode.length; i++) {
    26            decode[encode[i]] = i;
    27        }
    28        decode[pad] = 0;
    29    }
    30
    31    /**
    32     * Decode base64 chars to bytes.
    33     *
    34     * @param chars Chars to encode.
    35     *
    36     * @return Decoded bytes.
    37     */
    38    public static byte[] decode(char[] chars) {
    39        return decode(chars, decode, pad);
    40    }
    41
    42    /**
    43     * Encode bytes to base64 chars, with padding.
    44     *
    45     * @param bytes Bytes to encode.
    46     *
    47     * @return Encoded chars.
    48     */
    49    public static char[] encode(byte[] bytes) {
    50        return encode(bytes, encode, pad);
    51    }
    52
    53    /**
    54     * Encode bytes to base64 chars, with optional padding.
    55     *
    56     * @param bytes     Bytes to encode.
    57     * @param padded    Add padding to output.
    58     *
    59     * @return Encoded chars.
    60     */
    61    public static char[] encode(byte[] bytes, boolean padded) {
    62        return encode(bytes, encode, padded ? pad : 0);
    63    }
    64
    65    /**
    66     * Decode base64 chars to bytes using the supplied decode table and padding
    67     * character.
    68     *
    69     * @param src   Base64 encoded data.
    70     * @param table Decode table.
    71     * @param pad   Padding character.
    72     *
    73     * @return Decoded bytes.
    74     */
    75    public static byte[] decode(char[] src, int[] table, char pad) {
    76        int len = src.length;
    77
    78        if (len == 0) return new byte[0];
    79
    80        int padCount = (src[len - 1] == pad ? (src[len - 2] == pad ? 2 : 1) : 0);
    81        int bytes    = (len * 6 >> 3) - padCount;
    82        int blocks   = (bytes / 3) * 3;
    83
    84        byte[] dst = new byte[bytes];
    85        int si = 0, di = 0;
    86
    87        while (di < blocks) {
    88            int n = table[src[si++]] << 18 | table[src[si++]] << 12 | table[src[si++]] << 6 | table[src[si++]];
    89            dst[di++] = (byte) (n >> 16);
    90            dst[di++] = (byte) (n >>  8);
    91            dst[di++] = (byte) n;
    92        }
    93
    94        if (di < bytes) {
    95            int n = 0;
    96            switch (len - si) {
    97                case 4: n |= table[src[si+3]];
    98                case 3: n |= table[src[si+2]] <<  6;
    99                case 2: n |= table[src[si+1]] << 12;
   100                case 1: n |= table[src[si]]   << 18;
   101            }
   102            for (int r = 16; di < bytes; r -= 8) {
   103                dst[di++] = (byte) (n >> r);
   104            }
   105        }
   106
   107        return dst;
   108    }
   109
   110    /**
   111     * Encode bytes to base64 chars using the supplied encode table and with
   112     * optional padding.
   113     *
   114     * @param src   Bytes to encode.
   115     * @param table Encoding table.
   116     * @param pad   Padding character, or 0 for no padding.
   117     *
   118     * @return Encoded chars.
   119     */
   120    public static char[] encode(byte[] src, char[] table, char pad) {
   121        int len = src.length;
   122
   123        if (len == 0) return new char[0];
   124
   125        int blocks = (len / 3) * 3;
   126        int chars  = ((len - 1) / 3 + 1) << 2;
   127        int tail   = len - blocks;
   128        if (pad == 0 && tail > 0) chars -= 3 - tail;
   129
   130        char[] dst = new char[chars];
   131        int si = 0, di = 0;
   132
   133        while (si < blocks) {
   134            int n = (src[si++] & 0xff) << 16 | (src[si++] & 0xff) << 8 | (src[si++] & 0xff);
   135            dst[di++] = table[(n >>> 18) & 0x3f];
   136            dst[di++] = table[(n >>> 12) & 0x3f];
   137            dst[di++] = table[(n >>>  6) & 0x3f];
   138            dst[di++] = table[n          & 0x3f];
   139        }
   140
   141        if (tail > 0) {
   142            int n = (src[si] & 0xff) << 10;
   143            if (tail == 2) n |= (src[++si] & 0xff) << 2;
   144
   145            dst[di++] = table[(n >>> 12) & 0x3f];
   146            dst[di++] = table[(n >>> 6)  & 0x3f];
   147            if (tail == 2) dst[di++] = table[n & 0x3f];
   148
   149            if (pad != 0) {
   150                if (tail == 1) dst[di++] = pad;
   151                dst[di] = pad;
   152            }
   153        }
   154
   155        return dst;
   156    }
   157}