Initial bytes incorrect after Java AES/CBC decryption

前端 未结 10 2040
鱼传尺愫
鱼传尺愫 2020-11-22 12:47

What\'s wrong with the following example?

The problem is that the first part of the decrypted string is nonsense. However, the rest is fine, I get...

10条回答
  •  抹茶落季
    2020-11-22 13:15

    This is an improvement over the accepted answer.

    Changes:

    (1) Using random IV and prepend it to the encrypted text

    (2) Using SHA-256 to generate a key from a passphrase

    (3) No dependency on Apache Commons

    public static void main(String[] args) throws GeneralSecurityException {
        String plaintext = "Hello world";
        String passphrase = "My passphrase";
        String encrypted = encrypt(passphrase, plaintext);
        String decrypted = decrypt(passphrase, encrypted);
        System.out.println(encrypted);
        System.out.println(decrypted);
    }
    
    private static SecretKeySpec getKeySpec(String passphrase) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        return new SecretKeySpec(digest.digest(passphrase.getBytes(UTF_8)), "AES");
    }
    
    private static Cipher getCipher() throws NoSuchPaddingException, NoSuchAlgorithmException {
        return Cipher.getInstance("AES/CBC/PKCS5PADDING");
    }
    
    public static String encrypt(String passphrase, String value) throws GeneralSecurityException {
        byte[] initVector = new byte[16];
        SecureRandom.getInstanceStrong().nextBytes(initVector);
        Cipher cipher = getCipher();
        cipher.init(Cipher.ENCRYPT_MODE, getKeySpec(passphrase), new IvParameterSpec(initVector));
        byte[] encrypted = cipher.doFinal(value.getBytes());
        return DatatypeConverter.printBase64Binary(initVector) +
                DatatypeConverter.printBase64Binary(encrypted);
    }
    
    public static String decrypt(String passphrase, String encrypted) throws GeneralSecurityException {
        byte[] initVector = DatatypeConverter.parseBase64Binary(encrypted.substring(0, 24));
        Cipher cipher = getCipher();
        cipher.init(Cipher.DECRYPT_MODE, getKeySpec(passphrase), new IvParameterSpec(initVector));
        byte[] original = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted.substring(24)));
        return new String(original);
    }
    

提交回复
热议问题