eu.dety.burp.joseph.utilities.Decoder.java Source code

Java tutorial

Introduction

Here is the source code for eu.dety.burp.joseph.utilities.Decoder.java

Source

/**
 * JOSEPH - JavaScript Object Signing and Encryption Pentesting Helper
 * Copyright (C) 2016 Dennis Detering
 * <p>
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * <p>
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * <p>
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package eu.dety.burp.joseph.utilities;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;

import java.nio.charset.Charset;
import java.util.Arrays;

/**
 * Help functions to encode and decode JOSE values from different representations.
 * 
 * @author Dennis Detering
 * @version 1.0
 */
public class Decoder {
    private static final Logger loggerInstance = Logger.getInstance();

    /**
     * Safe URL encode a byte array to a String
     * 
     * @param input
     *            byte array input
     * @return base64url encoded string
     */
    public static String base64UrlEncode(byte[] input) {
        return new String(Base64.encodeBase64URLSafe(input));
    }

    /**
     * Split JOSE value into its separate parts
     * 
     * @param input
     *            Compact serialization JOSE value
     * @return string array with the separate parts
     */
    public static String[] getComponents(String input) {
        return input.split("\\.", -1);
    }

    /**
     * Split JOSE value into its separate parts with fixed length
     * 
     * @param input
     *            Compact serialization JOSE value
     * @param assureLength
     *            Assure a certain length of the returned string array
     * @return string array with the separate fixed amount of parts
     */
    public static String[] getComponents(String input, int assureLength) {
        String[] components = input.split("\\.");

        // If length is already correct return the components
        if (components.length == assureLength) {
            return components;
        }

        String[] output = new String[assureLength];
        Arrays.fill(output, "");

        System.arraycopy(components, 0, output, 0, Math.min(components.length, assureLength));

        return output;
    }

    /**
     * Join separate parts to JOSE value
     * 
     * @param input
     *            string array of JOSE values in compact serialization
     * @return single string with concatenated components
     */
    public static String concatComponents(String[] input) {
        return StringUtils.join(input, ".");
    }

    /**
     * Decode from base64url representation to string
     * 
     * @param input
     *            base64url encoded value
     * @return string representation of the base64 decoded value
     */
    public static String getDecoded(String input) {
        String output = "[ERROR]";

        try {
            output = new String(Base64.decodeBase64(input), Charset.forName("UTF-8"));
        } catch (Exception e) {
            loggerInstance.log(Decoder.class, e.getMessage(), Logger.LogLevel.ERROR);
        }

        return output;
    }

    /**
     * Decode from base64url representation to JSONObject
     * 
     * @param input
     *            base64url encoded value
     * @return JSONObject of the parsed value
     */
    public static JSONObject getDecodedJson(String input) {
        String decoded = getDecoded(input);
        JSONObject output = new JSONObject();

        if (decoded.equals("[ERROR]"))
            return output;

        try {
            output = new JSONObject(decoded);
        } catch (Exception e) {
            // decoded is no valid JSON string
            // loggerInstance.log(getClass(), e.getMessage(), Logger.ERROR);
        }

        return output;
    }

    /**
     * Get value by base64url string input and key name
     * 
     * @param input
     *            base64url string
     * @param key
     *            Name of the key
     * @return String value according to given key or empty string
     */
    public static String getValueByBase64String(String input, String key) {
        JSONObject jsonObj = Decoder.getDecodedJson(input);

        try {
            return jsonObj.get(key).toString();
        } catch (Exception e) {
            return "";
        }

    }

    /**
     * Decode from jose value to JSONObject array
     * 
     * @param input
     *            base64url encoded jose value string
     * @return JSONObject array of the parsed value
     */
    public static JSONObject[] getJsonComponents(String input) {
        String[] components = Decoder.getComponents(input);

        JSONObject[] output = new JSONObject[components.length];
        for (int i = 0; i < components.length; i++) {
            output[i] = Decoder.getDecodedJson(components[i]);
        }

        return output;
    }

    /**
     * Encode from JSON string to base64url representation
     * 
     * @param input
     *            JSON byte array
     * @return base64url representation of the JSON string
     */
    public static String getEncoded(byte[] input) {
        String output = "[ERROR]";

        try {
            output = base64UrlEncode(input);
        } catch (Exception e) {
            loggerInstance.log(Decoder.class, e.getMessage(), Logger.LogLevel.ERROR);
        }

        return output;
    }

    /**
     * Encode from JSON string to base64url representation
     * 
     * @param input
     *            JSON string
     * @return base64url representation of the JSON string
     */
    public static String getEncoded(String input) {
        String output = "[ERROR]";

        try {
            output = base64UrlEncode(input.getBytes(Charset.forName("UTF-8")));
        } catch (Exception e) {
            loggerInstance.log(Decoder.class, e.getMessage(), Logger.LogLevel.ERROR);
        }

        return output;
    }

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

    /**
     * Convert byte array to hex string
     * 
     * @param bytes
     *            Byte array input
     * @return Hex string
     */
    public static String bytesToHex(final byte[] bytes) {
        StringBuilder builder = new StringBuilder(bytes.length * 2);

        for (byte aByte : bytes) {
            // unsigned right shift of the MSBs
            builder.append(HEXCHARS[(aByte & 0xff) >>> 4]);
            // handling the LSBs
            builder.append(HEXCHARS[aByte & 0xf]);
            builder.append(' ');
        }

        return builder.toString().trim();
    }

    /**
     * Convert hex string to byte array
     * 
     * @param str
     *            Hex formatted string
     * @return Byte array
     */
    public static byte[] hexToBytes(String str) {
        str = str.replace(" ", "");
        int len = str.length();
        byte[] data = new byte[len / 2];

        try {
            for (int i = 0; i < len; i += 2) {
                data[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4)
                        + Character.digit(str.charAt(i + 1), 16));
            }
        } catch (Exception e) {
            data = new byte[0];
        }

        return data;
    }
}