如何手动解密EncryptedAssertion

时间:2018-02-07 22:51:13

标签: java saml-2.0 opensaml

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

当我在等待任何解决方案时,我试图手动解密它。它是一种混合加密

EncryptedAssertion

我试过下面的代码

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是我的加密数据的解密密钥。此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

2 个答案:

答案 0 :(得分:1)

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

你不应该只是用私钥解密calue。

首先使用RSA / ECB / PKCS1Padding解密KeyInfo值(解包aes密钥)(根据提供的saml片段)

它应该为您提供一个256位(32字节)随机密钥用于加密数据本身

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

进一步阅读

答案 1 :(得分:0)

csv.reader(f, delimiter='|', quotechar='|')
...
# [['question', '"N', '1', '2', '3', '4', '4', '30', '2', '"N', 'full_answer']]

ISO10126填充应该起作用。...