org.springframework.security.jwt.codec.Codecs.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.security.jwt.codec.Codecs.java

Source

/*
 * Copyright 2006-2011 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.springframework.security.jwt.codec;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;

/**
 * Functions for Hex, Base64 and Utf8 encoding/decoding
 *
 * @author Luke Taylor
 */
public class Codecs {
    private static Charset UTF8 = Charset.forName("UTF-8");

    /**
     * Base 64
     */
    public static byte[] b64Encode(byte[] bytes) {
        return Base64Codec.encode(bytes);
    }

    public static byte[] b64Decode(byte[] bytes) {
        return Base64Codec.decode(bytes);
    }

    // URL-safe versions with no padding chars
    public static byte[] b64UrlEncode(byte[] bytes) {
        return Base64.urlEncode(bytes);
    }

    public static byte[] b64UrlEncode(CharSequence value) {
        return b64UrlEncode(utf8Encode(value));
    }

    public static byte[] b64UrlDecode(byte[] bytes) {
        return Base64.urlDecode(bytes);
    }

    public static byte[] b64UrlDecode(CharSequence value) {
        return b64UrlDecode(utf8Encode(value));
    }

    /**
     * UTF-8 encoding/decoding. Using a charset rather than `String.getBytes` is less forgiving
     * and will raise an exception for invalid data.
     */
    public static byte[] utf8Encode(CharSequence string) {
        try {
            ByteBuffer bytes = UTF8.newEncoder().encode(CharBuffer.wrap(string));
            byte[] bytesCopy = new byte[bytes.limit()];
            System.arraycopy(bytes.array(), 0, bytesCopy, 0, bytes.limit());
            return bytesCopy;
        } catch (CharacterCodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String utf8Decode(byte[] bytes) {
        return utf8Decode(ByteBuffer.wrap(bytes));
    }

    public static String utf8Decode(ByteBuffer bytes) {
        try {
            return UTF8.newDecoder().decode(bytes).toString();
        } catch (CharacterCodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static char[] hexEncode(byte[] bytes) {
        return Hex.encode(bytes);
    }

    public static byte[] hexDecode(CharSequence s) {
        return Hex.decode(s);
    }

    // Substitute for Scala's Array.concat()
    public static byte[] concat(byte[]... arrays) {
        int size = 0;
        for (byte[] a : arrays) {
            size += a.length;
        }
        byte[] result = new byte[size];
        int index = 0;
        for (byte[] a : arrays) {
            System.arraycopy(a, 0, result, index, a.length);
            index += a.length;
        }
        return result;
    }
}

class Base64 {
    private static byte EQUALS = (byte) '=';

    static byte[] encode(byte[] bytes) {
        return Base64Codec.encode(bytes);
    }

    static byte[] decode(byte[] bytes) {
        return Base64Codec.decode(bytes);
    }

    static byte[] urlEncode(byte[] bytes) {
        byte[] b64Bytes = Base64Codec.encodeBytesToBytes(bytes, 0, bytes.length, Base64Codec.URL_SAFE);

        int length = b64Bytes.length;

        while (b64Bytes[length - 1] == EQUALS) {
            length -= 1;
        }

        byte[] result = new byte[length];
        System.arraycopy(b64Bytes, 0, result, 0, length);

        return result;
    }

    static byte[] urlDecode(byte[] b64) {
        // Pad with '=' as necessary before feeding to standard decoder
        byte[] b64Bytes = null;

        int lMod4 = b64.length % 4;

        if (lMod4 == 0) {
            b64Bytes = b64;
        } else if (lMod4 == 2) {
            b64Bytes = pad(b64, 2);
        } else if (lMod4 == 3) {
            b64Bytes = pad(b64, 1);
        } else {
            throw new IllegalArgumentException("Invalid Base64 string");
        }

        return Base64Codec.decode(b64Bytes, 0, b64Bytes.length, Base64Codec.URL_SAFE);
    }

    private static byte[] pad(byte[] bytes, int n) {
        int l = bytes.length;
        byte[] padded = new byte[l + n];
        System.arraycopy(bytes, 0, padded, 0, l);
        for (int i = l; i < l + n; i++) {
            padded[i] = EQUALS;
        }
        return padded;
    }
}

class Hex {
    private static final char[] HEX = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
            'd', 'e', 'f' };

    static char[] encode(byte[] bytes) {
        int nBytes = bytes.length;
        char[] result = new char[2 * nBytes];

        int j = 0;
        for (int i = 0; i < nBytes; i++) {
            // Char for top 4 bits
            result[j] = HEX[(0xF0 & bytes[i]) >>> 4];
            // Bottom 4
            result[j + 1] = HEX[(0x0F & bytes[i])];
            j += 2;
        }
        return result;
    }

    static byte[] decode(CharSequence s) {
        int nChars = s.length();
        if (nChars % 2 != 0) {
            throw new IllegalArgumentException("Hex-encoded string must have an even number of characters");
        }

        byte[] result = new byte[nChars / 2];

        for (int i = 0; i < nChars; i += 2) {
            int msb = Character.digit(s.charAt(i), 16);
            int lsb = Character.digit(s.charAt(i + 1), 16);
            if (msb <= 0 || lsb <= 0) {
                throw new IllegalArgumentException("Non-hex character in input: " + s);
            }
            result[i / 2] = (byte) ((msb << 4) | lsb);
        }
        return result;
    }
}