Private Key for MLE decryption

Renuka
New Contributor

Private Key for MLE decryption

Dear Visa team,

 

I'm encountering an issue with the decryption of MLE response.
I have used the below Java code 

MLEResponse mleResponse = getMleResponse(encryptedResponseStr);
String encData = mleResponse.getEncData();
JWEObject jweObject = JWEObject.parse(encData);
jweObject.decrypt(new RSADecrypter(getRSAPrivateKey()));
decryptedResponse = jweObject.getPayload().toString();

System.out.println("plainResponseplainResponse " + decryptedResponse);


static class MLEResponse {
private String encData;
 
public String getEncData() {
return encData;
}
 
public void setEncData(String encData) {
this.encData = encData;
}
 
@Override
public String toString() {
return "MLEResponse{" + "encData='" + encData + '\'' + '}';
}
}
 
public static MLEResponse getMleResponse(String encData) throws IOException {
 
ObjectMapper mapper = new ObjectMapper();
 
return mapper.readValue(encData, MLEResponse.class);
}
 
protected static PrivateKey getRSAPrivateKey()
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
String BEGIN_RSA_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----";
String END_RSA_PRIVATE_KEY = "-----END PRIVATE KEY-----";
 
String privateKey =MLE_CLIENT_PRIVATE_KEY_PATH; 
 
String pemEncodedKey = IOUtils.readFileToString(new File(privateKey), Charset.forName("UTF-8"));
System.out.println("PenEncodeKey:::"+pemEncodedKey);
com.nimbusds.jose.util.Base64 base64 = new com.nimbusds.jose.util.Base64(pemEncodedKey.replaceAll(BEGIN_RSA_PRIVATE_KEY, "").replaceAll(END_RSA_PRIVATE_KEY, ""));
ASN1Sequence primitive = (ASN1Sequence) ASN1Sequence.fromByteArray(base64.decode());
Enumeration<?> e = primitive.getObjects();
BigInteger v = ((ASN1Integer) e.nextElement()).getValue();
int version = v.intValue();
if (version != 0 && version != 1) {
throw new IllegalArgumentException("wrong version for RSA private key");
}
BigInteger modulus = ((ASN1Integer) e.nextElement()).getValue();
((ASN1Integer) e.nextElement()).getValue();
BigInteger privateExponent = ((ASN1Integer) e.nextElement()).getValue();
((ASN1Integer) e.nextElement()).getValue();
((ASN1Integer) e.nextElement()).getValue();
((ASN1Integer) e.nextElement()).getValue();
((ASN1Integer) e.nextElement()).getValue();
((ASN1Integer) e.nextElement()).getValue();
RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(modulus, privateExponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return (PrivateKey) keyFactory.generatePrivate(privateKeySpec);
}
Here my confusion is am i extracting the private key properly or not 

I have exported the p12 to file from the JKS file(which is used for MLE keyID) and then converted to pem format.
Unfortunately, decryption is not working.


Kindly help to resolve this issue and guide me to extract the private key as well.
Thanks in advance
4 REPLIES 4
SyedSa
Community Moderator

Re: Private Key for MLE decryption

Hi @Renuka, Thank you for reaching out. One of our agents will look into this and get back to you soon. If any community member knows a solution, please feel free to reply to this thread.

shameem
Visa Employee

Re: Private Key for MLE decryption

Hi @Renuka ,

 

I can see that from your code that the private key is in PKCS format not an RSA format.

 

To load a private which is in PKCS format as RSA you need to simply do the following. Please give it a try and let us know how it went.

public static RSAPrivateKey getRSAPrivateKey(String mleClientPrivateKeyPath) throws GeneralSecurityException {
        String BEGIN_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----";
        String END_PRIVATE_KEY = "-----END PRIVATE KEY-----";
        String LINE_SEPARATOR = "\r\n";
        String privateKey = mleClientPrivateKeyPath.replace(BEGIN_PRIVATE_KEY, "")
                .replaceAll(LINE_SEPARATOR, "")
                .replace(END_PRIVATE_KEY, "");
        byte[] encodedPrivateKey = Base64.getDecoder().decode(privateKey);
        return (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(encodedPrivateKey));
    }

 

Thank you.

Shameem

Renuka
New Contributor

Re: Private Key for MLE decryption

Hi @shameem ,

Thank you for your prompt response.

I've implemented the suggested code snippet, but encountered an error:
Visa Exception: ****Illegal base64 character 3a java.lang.IllegalArgumentException: Illegal base64 character 3a response {"VisaMessage":"Illegal base64 character 3a","ExceptionMessage":"Illegal base64 character 3a","ErrorMessage":"Unable to connect"}

I suspect the issue lies in how I extracted the private key. Here are the commands I used:

keytool -importkeystore -srckeystore path\clientkeystore.jks -destkeystore path\clientkeystoretemp.p12 -deststoretype PKCS12 -srcalias client -deststorepass pass -destkeypass pass

openssl pkcs12 -in path\clientkeystoretemp.p12 -nocerts -nodes -out path\cbzsandboxprivatekey.pem -passin pass:pass -passout pass:pass

 

I haven't shared the actual passwords and aliases used.

Could you guide me on the correct method to extract the RSA private key and provide the corresponding code snippet to decrypt the encrypted MLE response?

 

Looking forward to your guidance.

shameem
Visa Employee

Re: Private Key for MLE decryption

Hi @Renuka ,

Kindly ensure you are using the correct public/private key pairs for encryption/decryption and for mutual auth. See your project credentials.

Use the MLE private key file provided/downloaded from Visa Developer Portal when you generate the MLE Key-ID.

 

MLE Cert and Key should contain the Key ID

MLE_CLIENT_PRIVATE_KEY_PATH = "key_<KEY_ID>.pem";
MLE_SERVER_PUBLIC_CERTIFICATE_PATH = "<server_cert_<KEY_ID>.pem";
KEY_ID = "<YOUR KEY ID>";

Not sure why there is a need to add it to a keystore and extract it again.  

Please follow the instructions provided here https://community.developer.visa.com/t5/Message-Level-Encryption/How-to-run-Java-Sample-Code-for-MLE...

 

Thank you.