How to use Bouncy Castle lightweight API with AES and PBE

前端 未结 4 954
清酒与你
清酒与你 2020-12-08 17:47

I have a block of ciphertext that was created using the JCE algorithim \"PBEWithSHA256And256BitAES-CBC-BC\". The provider is BouncyCastle. What I\'d like to do it decrypt th

相关标签:
4条回答
  • 2020-12-08 18:18

    There were a few problems with your decrypt method:

    private static byte[] decrypt(final byte[] bytes, final char[] password, final byte[] salt) throws DataLengthException, IllegalStateException, InvalidCipherTextException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
    
        final PBEParametersGenerator keyGenerator = new PKCS12ParametersGenerator(new SHA256Digest());
        keyGenerator.init(PKCS12ParametersGenerator.PKCS12PasswordToBytes(password), salt, 20);
        final CipherParameters keyParams = keyGenerator.generateDerivedParameters(256, 128);
    
        final BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()), new PKCS7Padding());
        cipher.init(false, keyParams);
    
        final byte[] processed = new byte[cipher.getOutputSize(bytes.length)];
        int outputLength = cipher.processBytes(bytes, 0, bytes.length, processed, 0);
        outputLength += cipher.doFinal(processed, outputLength);
    
        final byte[] results = new byte[outputLength];
        System.arraycopy(processed, 0, results, 0, outputLength);
        return results;
    }
    

    The main problems were the way you were carrying out the decryption without using a block cipher and the missing IV size to the generateDerivedParameters method. I saw the first problem pretty quickly, the 2nd one was much less obvious. I only discovered that one through looking at a Bouncy Castle test called PBETest.

    0 讨论(0)
  • 2020-12-08 18:20

    I noticed that your encryption method accepts a password as a char array but the decrypt accepts password as bytes. In Java chars are 16-bit while bytes are 8-bit. This could result in different keys for encrypt/decrypt and perhaps explain the issues with gibberish decrypted results?

    0 讨论(0)
  • 2020-12-08 18:23

    I tried this and it seemed to work. Borrowed heavily from the BC class org.bouncycastle.jce.provider.test.PBETest

    private byte[] decryptWithLWCrypto(byte[] cipher, String password, byte[] salt, final  int iterationCount)
            throws Exception
    {
        PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(new SHA256Digest());
        char[] passwordChars = password.toCharArray();
        final byte[] pkcs12PasswordBytes = PBEParametersGenerator
                .PKCS12PasswordToBytes(passwordChars);
        pGen.init(pkcs12PasswordBytes, salt, iterationCount);
        CBCBlockCipher aesCBC = new CBCBlockCipher(new AESEngine());
        ParametersWithIV aesCBCParams = (ParametersWithIV) pGen.generateDerivedParameters(256, 128);
        aesCBC.init(false, aesCBCParams);
        PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(aesCBC,
                new PKCS7Padding());
        byte[] plainTemp = new byte[aesCipher.getOutputSize(cipher.length)];
        int offset = aesCipher.processBytes(cipher, 0, cipher.length, plainTemp, 0);
        int last = aesCipher.doFinal(plainTemp, offset);
        final byte[] plain = new byte[offset + last];
        System.arraycopy(plainTemp, 0, plain, 0, plain.length);
        return plain;
    }
    
    0 讨论(0)
  • 2020-12-08 18:30

    It's not trivial to generate the key exactly as the JCE counterparts. I just briefly browsed your code. Found at least one discrepancy. JCE uses PKCS12 generator but you use PKCS5S1.

    I am not surprised if there are other differences. You need to compare your code against BC source.

    0 讨论(0)
提交回复
热议问题