Main.java Source code

Java tutorial

Introduction

Here is the source code for Main.java

Source

//package com.java2s;
/*
 * 
 * Copyright (C) 2015 Orange Labs
 * 
 * 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
 * 
 *    http://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.
 * 
 */

import java.nio.ByteBuffer;

import java.security.Key;

import java.util.Arrays;
import java.util.StringTokenizer;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
import android.util.Log;

public class Main {
    final protected static char[] hexArrayM = "0123456789ABCDEF".toCharArray();

    static byte[] decryptJWE(String jwe, Key privRsaKey) {
        // Log.d("","decryptJWE");

        try {
            // split jwe string
            StringTokenizer tokens = new StringTokenizer(jwe, ".");
            int count = tokens.countTokens();
            // Log.d("","parts.length: "+count);

            if (count != 5)
                return null;

            String jweProtectedHeader64 = tokens.nextToken();
            String jweEncrypted64 = tokens.nextToken();
            String jweInitVector64 = tokens.nextToken();
            String cryptedBytes64 = tokens.nextToken();
            String auth_tag64 = tokens.nextToken();

            // decrypt cek using private rsa key
            byte[] cek = decryptRsaB64(jweEncrypted64, privRsaKey);

            // check cek result byte array
            if (cek == null || cek.length == 0 || (cek.length % 2) != 0)
                return null;

            int keySize = cek.length / 2;
            Log.d("", "Decryption AES: " + keySize * 8);

            // build aes_key and hmac_key
            byte aes_key[] = new byte[keySize];
            byte hmac_key[] = new byte[keySize];

            System.arraycopy(cek, 0, hmac_key, 0, keySize);
            System.arraycopy(cek, keySize, aes_key, 0, keySize);

            // decode initialization vector
            byte[] iv_key = decodeB64(jweInitVector64);

            Log.d("", "hmac_key: " + bytesToHex(hmac_key));
            Log.d("", "aes_key:  " + bytesToHex(aes_key));
            Log.d("", "iv_key:   " + bytesToHex(iv_key));

            // decrypt content using aes_key and iv_key
            byte[] cryptedBytes = decodeB64(cryptedBytes64);
            Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SC");
            decrypt.init(Cipher.DECRYPT_MODE, new SecretKeySpec(aes_key, "AES"), new IvParameterSpec(iv_key));
            byte[] decryptedBytes = decrypt.doFinal(cryptedBytes);

            Log.d("", "decryptedBytes:");
            Log.d("", bytesToHex(decryptedBytes));

            // validation verification
            byte[] aad = jweProtectedHeader64.getBytes();
            long al = aad.length * 8;

            // concatenate aad, iv_key, cryptedBytes and al 
            byte[] hmacData = new byte[aad.length + iv_key.length + cryptedBytes.length + 8];
            int offset = 0;
            System.arraycopy(aad, offset, hmacData, 0, aad.length);
            offset += aad.length;
            System.arraycopy(iv_key, 0, hmacData, offset, iv_key.length);
            offset += iv_key.length;
            System.arraycopy(cryptedBytes, 0, hmacData, offset, cryptedBytes.length);
            offset += cryptedBytes.length;
            ByteBuffer buffer = ByteBuffer.allocate(8);
            buffer.putLong(al);
            System.arraycopy(buffer.array(), 0, hmacData, offset, 8);

            // compute hmac
            Mac hmac = Mac.getInstance("HmacSHA256", "SC");
            hmac.init(new SecretKeySpec(hmac_key, "HmacSHA256"));
            byte[] hmacValue = hmac.doFinal(hmacData);

            // pick authentication tag
            byte[] authTag = Arrays.copyOf(hmacValue, 16);

            // validate authentication tag
            byte[] authTagRead = decodeB64(auth_tag64);
            for (int i = 0; i < 16; i++) {
                if (authTag[i] != authTagRead[i]) {
                    Log.d("", "validation failed");
                    return decryptedBytes;
                }
            }

            Log.d("", "validation success");

            // validation success
            return decryptedBytes;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    static byte[] decryptRsaB64(String s64, Key privRsaKey) {
        try {
            byte[] sBytes = decodeB64(s64);
            if (sBytes != null) {
                Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "SC");
                cipher.init(Cipher.DECRYPT_MODE, privRsaKey);
                return cipher.doFinal(sBytes);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    static byte[] decodeB64(String s64) {
        return Base64.decode(s64, Base64.URL_SAFE);
    }

    public static String bytesToHex(byte[] bytes) {
        int nSize = 2; // 3;
        char[] hexChars = new char[bytes.length * nSize];
        int v;
        for (int j = 0; j < bytes.length; j++) {
            v = bytes[j] & 0xFF;
            hexChars[j * nSize] = hexArrayM[v >>> 4];
            hexChars[j * nSize + 1] = hexArrayM[v & 0x0F];
            // hexChars[j * nSize + 2] = ' ';
        }

        return new String(hexChars);
    }

    public static String bytesToHex(byte[] bytes, String sep) {
        if (sep == null)
            sep = "";

        int nSize = 2; // 3;
        StringBuffer sb = new StringBuffer((bytes.length + sep.length()) * nSize);
        int v;
        for (int j = 0; j < bytes.length; j++) {
            v = bytes[j] & 0xFF;
            sb.append(sep);
            sb.append(hexArrayM[v >>> 4]);
            sb.append(hexArrayM[v & 0x0F]);
        }

        return sb.toString();
    }
}