如何手动解密 EncryptedAssertion

How to decrypt EncryptedAssertion manually

我想解密 EncryptedAssertion。我尝试使用 OpenSaml Decrypter,但它不适用于 me.I 我无法解密 EncryptedData 我已经问过这个问题了 - EncryptedAssertion Decryption failing

在等待任何解决方案的同时,我正在尝试手动解密它。它是混合加密

我试过下面的代码

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)));

我不确定我是否走在正确的道路上,但上面的 decryptedValue 是我加密的解密密钥 Data.This decryptedValue 不是可读格式。不确定下一步该做什么。

getPrivateKey 方法

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

根据我的建议,我编码如下。不确定我做的是否正确我也收到错误

 `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)));`

错误 -

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)

更新:: 希望我根据评论正确地做到了。

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

我不会为您提供完整的答案,但我希望能让您走上正轨

你不应该只是简单地用私钥解密计算。

首先使用RSA/ECB/PKCS1Padding(根据提供的 saml 片段)

解密 KeyInfo 值(解开 aes 密钥)

它应该给你一个 256 位(32 字节)的随机密钥,用于加密数据本身

然后使用 AES 密钥解密数据。请注意,第一个字节(128 位/16 字节,aes 块大小)用作 IV。

进一步阅读

    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;
}

ISO10126 填充应该有效....