Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to convert a WebCrypto key pair to Java RSA keys

I have public key and private key as string which are generated from Webcrypto API RSA-OAEP algorithm. I want to encrypt and decrypt some plain text by using those and getting exception when trying to convert string to byte array

Java code:

package mailsend;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.Cipher;

public class RsaOaep {
  public static void main(String[] args) throws Exception {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

    //Encryption
    byte[] input = "{\"userid\":\"1242\",\"appid\":\"1234\",\"tenentid\":\"4567\",\"sessionid\":\"session1234567\"}".getBytes();
    Cipher cipher = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");
    SecureRandom random = new SecureRandom();
    String publicKey="{\n" + 
            "  \"alg\": \"RSA-OAEP-256\",\n" + 
            "  \"e\": \"AQAB\",\n" + 
            "  \"ext\": true,\n" + 
            "  \"key_ops\": [\n" + 
            "    \"encrypt\"\n" + 
            "  ],\n" + 
            "  \"kty\": \"RSA\",\n" + 
            "  \"n\": \"uChD48P6OBCynflLVsuP51hExmS7JIJmSPe6g_RYeb-O8rbaJA6mJE7QsMBeCrBUeyjhFYOFkGV9tpu3xIMkuRmTiyqy_mP2DKo8x9RB0gGVRvDuFjyOb3qpTAEA1SGyo_jGwN3RmVAVzVOTAAHqgQpRHtUsFEpQImUJgOUGVAfyFYpyyJKypcRv-RIU2JxOg3w7-i53erZPMHq_eWzEEXOgAU49UPjlTV18bXklBKSy3sbhKDpvHvOh_rEufhtD1Jl5RAQz3o8GGWPmcSf_3h5xa5ppqcgx6cfHDY9KKgxgCScwtjzTqU_QJO_zRnf3kYFU4dIFkfpXOJDDJc6RwQ\"\n" + 
            "}";
    byte[] keyBytes = Base64.getDecoder().decode(publicKey);
    PublicKey publicKeyNew = KeyFactory.getInstance("RSA", "BC").generatePublic(new X509EncodedKeySpec(keyBytes));
    cipher.init(Cipher.ENCRYPT_MODE, publicKeyNew, random);
    byte[] cipherText = cipher.doFinal(input);
    System.out.println("cipher: " + new String(cipherText));

    //Decryption
    String privateKey="{\n" + 
            "  \"alg\": \"RSA-OAEP-256\",\n" + 
            "  \"d\": \"FZO8Lp_r_a0xLHLE6cjElePg_QjY54Ry1RpXi3Xx9uPjrRsREJf5zffBGnCTpDd4Uozd4I4uNFa75c01eSwvfZOaVrw8SDOwpNe-cuBzDNbcJXl9v_O88aFi3DGi5hYCbxVrPjZPRGIeh9YCu4W98vwhOJZcCY2SeZEyjZxoAyjOmsvvylpUVN2ZVJ22lDOaBJMerPdwyXFv9wsUserFleZByk-M8WLz5JiT3MIg6NuMiMryx3-lhcHCBXgHJMeuxrdnPc_acer3WNkgWf5Q4LkTu9TT_Uz4kULtPvdbccv3-JyE0x4ZjCfiAmT65vUM5WvmCE6MZseR3WONIxmh0Q\",\n" + 
            "  \"dp\": \"FdzMUisoeG6Kk4C7Ol7k3QqR6QKa18LsMVIQXruQ7Vxm4bJ0lo8WyHWhLy4n11JLs7OGFENyXu7NtXw0ezmolfKIJVlItxWofICm8wm3Rhljrxe9KJnp1V4L1ibCXLOXOLsqhUwesWOhjAkfTHWJf3-wslSxVtFbif3fjeaKHlk\",\n" + 
            "  \"dq\": \"YTfHIEIOYiJ9AW_r3R8ou69ApwyzFNqczSeVooMKvKTYrpdj4ms6MeW5uL8Pq9HKFr8AFA2FWtOvrHrxShw_1V9IuvNChmPEF11RIO7CSc6xeK98zFtgqzbpJ81SKlcKh4icpaSjX3SQa7qbasgk9MBxK5gmpc5XZZNICDKfZ-E\",\n" + 
            "  \"e\": \"AQAB\",\n" + 
            "  \"ext\": true,\n" + 
            "  \"key_ops\": [\n" + 
            "    \"decrypt\"\n" + 
            "  ],\n" + 
            "  \"kty\": \"RSA\",\n" + 
            "  \"n\": \"uChD48P6OBCynflLVsuP51hExmS7JIJmSPe6g_RYeb-O8rbaJA6mJE7QsMBeCrBUeyjhFYOFkGV9tpu3xIMkuRmTiyqy_mP2DKo8x9RB0gGVRvDuFjyOb3qpTAEA1SGyo_jGwN3RmVAVzVOTAAHqgQpRHtUsFEpQImUJgOUGVAfyFYpyyJKypcRv-RIU2JxOg3w7-i53erZPMHq_eWzEEXOgAU49UPjlTV18bXklBKSy3sbhKDpvHvOh_rEufhtD1Jl5RAQz3o8GGWPmcSf_3h5xa5ppqcgx6cfHDY9KKgxgCScwtjzTqU_QJO_zRnf3kYFU4dIFkfpXOJDDJc6RwQ\",\n" + 
            "  \"p\": \"_8_ViZjqi4qU0jdt4dbrv81-FYFjJ0A3CpHhOwDxvIHRBMTS188_SEe-CZFwF91myv3AF9ZA64gYscr6t765F3-R7ydygryQWOedE-meRZhUHw3E3y-w_Khvtv0k3DW_NBO1-i3MDi8HV-xoSED9_ZYP6B0N05sBeoLhr76MuVk\",\n" + 
            "  \"q\": \"uErwgmSi7_t90oqKEED4Da8csEZVBN6_7n9xbZEk366lPf5rPETPbr8DKG-rA4kXq3l10ZksC-oo0RKdMpnqoHiYjmFPex1uLXJOAR_sg8ENtYtH-U6tNBjpoLufnbtg39O4bT7jr0HXx3MQmNy4rumfO97XypqIdKkrAODtJqk\",\n" + 
            "  \"qi\": \"brnAuBOvNKKdkwsI836lPNxmKqAMc-Jbtn7YmOu3ofq6PtiT5blJSGUJizMd1YDRHTLlQzWt1eqFZr_AjidGZ0QvYSj1jZT1hdpkIGn1M6oDDwh73mDC_Wqg5qtyFp6YudzWpSt5TG7m94pyPFx79wm1WedW53RVNQVdx3yOcBI\"\n" + 
            "}";
    byte[] keyBytesNew = Base64.getDecoder().decode(privateKey);
    PrivateKey privateKeyNew = KeyFactory.getInstance("RSA", "BC").generatePrivate(new X509EncodedKeySpec(keyBytesNew));
    cipher.init(Cipher.DECRYPT_MODE, privateKeyNew);
    byte[] plainText = cipher.doFinal(cipherText);
    System.out.println("plain : " + new String(plainText));
  }
}

Exception:

Exception in thread "main" java.lang.IllegalArgumentException: Illegal base64 character 7b at java.util.Base64$Decoder.decode0(Base64.java:714) at java.util.Base64$Decoder.decode(Base64.java:526) at java.util.Base64$Decoder.decode(Base64.java:549) at mailsend.RsaOaep.main(RsaOaep.java:30)

like image 321
rajasekhar pippalla Avatar asked Feb 06 '18 08:02

rajasekhar pippalla


1 Answers

The keys exported by the webcrypto are in JWK (JSON Web Key) format. Java does not directly support this format, so you must first process the components of the RSA key pair

Once you have generated the keys correctly you can check your encryption code

1. Decode de JSON Web Key: Parse the JSON string and extract the components ot the public and private key

I suggest to use a JSON library like Jackson. See this sample

public class JWK{
    String n;
    String e;
    //getters and setters
} 

ObjectMapper mapper = new ObjectMapper();
JWK jwk = mapper.readValue(publicKeyJson, JWK.class);

2. Convert key components to BigInteger: modulus, public exponent, private exponent, etc are encoded as base64url strings. Decode these strings to byte[] and use them to build BigInteger, so they could be loaded by Java Key builders

byte[] publicExponentBytes = Base64.getUrlDecoder().decode(jwkPublic.e);
byte[] privateExponentBytes = Base64.getUrlDecoder().decode(jwkPrivate.d);
byte[] modulusBytes = Base64.getUrlDecoder().decode(jwkPublic.n);

BigInteger publicExponent = new BigInteger(1, publicExponentBytes );
BigInteger privateExponent = new BigInteger(1, privateExponentBytes);
BigInteger modulus = new BigInteger(1, modulusBytes);

3. Build public key using modulus (n) and public exponent(e)

RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent );
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKey = factory.generatePublic(spec);

4. Build private key using modulus (n) and private exponent(d)

RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(modulus, privateExponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = factory.generatePrivate(privateKeySpec);
like image 163
pedrofb Avatar answered Sep 20 '22 08:09

pedrofb