user1544460
user1544460

Reputation: 193

How to decrypt EncryptedAssertion manually

I want to decrypt the EncryptedAssertion. I tried with OpenSaml Decrypter but its not working for me.I am getting Failed to decrypt EncryptedData I have already ask that question - EncryptedAssertion Decryption failing

While I am waiting for any solution I am trying to decrypt it manually. Its a Hybrid encryption

EncryptedAssertion

I tried below code

CipherValue cv = encryptedAssertion.getEncryptedData().getKeyInfo().getEncryptedKeys().get(0).getCipherData().getCipherValue();
String cvalue = cv.getValue();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
String decryptedValue = new String(cipher.doFinal(DatatypeConverter.parseBase64Binary(cvalue)));

I am not sure if I am on the right path, but above decryptedValue is the decryption key for my Encrypted Data.This decryptedValue is not in readable format. Not sure what to do next.

getPrivateKey method

   public PrivateKey getPrivateKey(){
    Key key = null;
    PrivateKey privateKey = null;
    try {
        KeyStore ks = KeyStore.getInstance("pkcs12", "SunJSSE");         
        ks.load(new FileInputStream("prvkey.pfx"),"".toCharArray());
         Enumeration<String> aliases = ks.aliases();
         while(aliases.hasMoreElements()){
             String alias = aliases.nextElement();
             key  = ks.getKey(alias, "".toCharArray());
             privateKey = (PrivateKey)key; 
        }

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

Based on the suggestion I coded like below. Not sure if I am doing it correct also I am getting errors

 `CipherValue cv = encryptedAssertion.getEncryptedData().getKeyInfo().getEncryptedKeys().get(0).getCipherData().getCipherValue(); 
String cvalue = cv.getValue();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.UNWRAP_MODE, getPrivateKey());
Key decryptionKey = cipher.unwrap(DatatypeConverter.parseBase64Binary(cvalue), "RSA/ECB/PKCS1Padding", Cipher.SECRET_KEY);

CipherValue cdata = encryptedAssertion.getEncryptedData().getCipherData().getCipherValue();
String cdataValue = cdata.getValue();

byte[] iv = new byte[256 / 16];
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);              
Cipher cipher2 = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec spec = new SecretKeySpec(decryptionKey.getEncoded(), "AES"); 
cipher2.init(Cipher.DECRYPT_MODE, spec, ivParamSpec );
String decryptedValue = new String(cipher2.doFinal(DatatypeConverter.parseBase64Binary(cdataValue)));`

Error -

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2121)

UPDATE :: hope I am doing it correctly based on the comments.

byte[] iv = new byte[256/16];
iv = Arrays.copyOfRange(DatatypeConverter.parseBase64Binary(cdataValue), 0,  16);
byte[] cipherBlock = Arrays.copyOfRange(DatatypeConverter.parseBase64Binary(cdataValue), 16,  DatatypeConverter.parseBase64Binary(cdataValue).length);

IvParameterSpec ivParamSpec = new IvParameterSpec(iv);              
Cipher cipher2 = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec spec = new SecretKeySpec(decryptionKey.getEncoded(), "AES");
cipher2.init(Cipher.DECRYPT_MODE, spec, ivParamSpec );
String decryptedValue = new String(cipher2.doFinal(cipherBlock)); // Same error - Given final block not properly padded

Upvotes: 1

Views: 4649

Answers (2)

Venkateswara Rao
Venkateswara Rao

Reputation: 5392

    public static byte[] decrypt(byte[] cryptoBytes, byte[] aesSymKey)
        throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
        InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
    // https://github.com/onelogin/java-saml/issues/23
    String cipherMethod = "AES/CBC/ISO10126Padding"; // This should be derived from Cryptic Saml

    AlgorithmParameterSpec iv = new IvParameterSpec(cryptoBytes, 0, 16);
    
    // Strip off the the first 16 bytes because those are the IV
    byte[] cipherBlock = Arrays.copyOfRange(cryptoBytes,16, cryptoBytes.length);
            
    // Create a secret key based on symKey
    SecretKeySpec secretSauce = new SecretKeySpec(aesSymKey, "AES");

    // Now we have all the ingredients to decrypt
    Cipher cipher = Cipher.getInstance(cipherMethod);
    cipher.init(Cipher.DECRYPT_MODE, secretSauce, iv);

    // Do the decryption
    byte[] decrypedBytes = cipher.doFinal(cipherBlock);
    return decrypedBytes;
}

ISO10126Padding should work....

Upvotes: 1

gusto2
gusto2

Reputation: 12075

I won't provide you a complete answer but I hope to get you on the right track

You should not just simply decrypt the calue with the private key.

First decrypt the KeyInfo value (unwrap the aes key) using RSA/ECB/PKCS1Padding (according to the provided saml snippet)

It should give you a 256 bit (32 bytes) random key used to encrypt data itself

then use the AES key to decrypt the data . Please note that first bytes (128 bit / 16 bytes, aes block size) is used as IV.

further reading

Upvotes: 1

Related Questions