Java tutorial
//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(); } }