【问题标题】:How to decrypt EncryptedAssertion manually如何手动解密 EncryptedAssertion
【发布时间】:2018-02-07 22:51:12
【问题描述】:

我想解密 EncryptedAssertion。我尝试使用 OpenSaml Decrypter,但它对我不起作用。我无法解密 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 是我的加密数据的解密密钥。这个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)

更新:: 希望我根据 cmets 正确地做。

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

【问题讨论】:

    标签: java saml-2.0 opensaml


    【解决方案1】:

    我不会给你一个完整的答案,但我希望能让你走上正轨

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

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

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

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

    进一步阅读

    【讨论】:

    • 我根据您提供的建议/链接进行了编码。我已经更新了这个问题。
    • 假设错误Given final block not properly padded来自第二次(数据)解密,IV使用方式错误。密文的第一个块(cdataValue)需要填入IV,只解密其余的密文
    • 是的,错误来自第二次数据解密。希望我明白你在说什么,我试图这样做但仍然出错。
    • 当我不使用填充时它工作得很好Cipher cipher2 = Cipher.getInstance("AES/CBC/NoPadding");
    • @user1544460 这意味着必须以不同方式填充原始值(不是 pkcs 填充)
    【解决方案2】:
        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 应该可以工作....

    【讨论】:

      猜你喜欢
      • 2017-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-19
      • 1970-01-01
      • 2017-08-08
      • 2016-05-21
      相关资源
      最近更新 更多