0

I have been trying to convert an AES decryption function from Java to Dart.

It uses AES with, IV and salt. No padding operations are performed.

This is the Java code:

    public byte[] Decrypt(byte[] Data, String Password) throws InvalidKeyException, InvalidAlgorithmParameterException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
        byte[] salt = new byte[8];
        byte[] iv = new byte[16];
        System.arraycopy(Data, 0, salt, 0, 8);
        System.arraycopy(Data, 8    , iv, 0, 16);
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec =
                new PBEKeySpec(Password.toCharArray(),salt, 1024, 128);
        SecretKey tmp = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
        Cipher d = Cipher.getInstance("AES/CBC/PKCS5Padding");
        d.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
        byte[] t = new byte[Data.length - 24];
        System.arraycopy(Data, 24, t, 0, t.length);
        
        return d.doFinal(t);
    }

and this is my Dart attempt:

 static Uint8List? decrypt(String ciphertext, String password) {
    Uint8List rawCipher = base64.decode(ciphertext);
    var salt = rawCipher.sublist(0, 0 + 8);
    var iv = rawCipher.sublist(8, 8 + 16);
    var encrypted = rawCipher.sublist(8 + 16);

    Uint8List key = generateKey(password, salt);
    print('key => $key');
    CBCBlockCipher cipher = CBCBlockCipher(AESEngine());


    ParametersWithIV<KeyParameter> params =
    ParametersWithIV<KeyParameter>(KeyParameter(key), iv);
    PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, Null>
    paddingParams =
    PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, Null>(
        params, null);
    PaddedBlockCipherImpl paddingCipher =
    PaddedBlockCipherImpl(PKCS7Padding(), cipher);
    paddingCipher.init(false, paddingParams);

    var val = paddingCipher.process(encrypted);

    String res = String.fromCharCodes(val);

    print('res => $res');

    return val;
  }



  static Uint8List generateKey(String passphrase, Uint8List salt) {
    Uint8List passphraseInt8List = Uint8List.fromList(passphrase.codeUnits);

    KeyDerivator derivator = PBKDF2KeyDerivator(HMac(SHA1Digest(), 32));
    Pbkdf2Parameters params = Pbkdf2Parameters(salt, 1024, 16);
    derivator.init(params);
    return derivator.process(passphraseInt8List);
  }

base64 encrypted string :

7MT6+nT/grYuh6vAwMGtt/2YXddNbdPY2uijM3HrHQ4q5Iv8Q8zm2emMuuXtaMdHHDId23hNYdrs
rhK2pUXfvRE7S/evuQa2UwjV9PsSMicSFxT8LZgOYsjL73zGuUGGhCTqk3NwtXGSzNsPMMAMsjOO
bbrl5N42TAouLvsaOmiMqjDYPItE3l0GfVYtdIf3vDN5hc7wUDI0Kq4WuXLDaSEK1IyO90KY4+LC
fc/9hwRv1iW96UK71wEYeWL1UV6ij3ACRNTR4uM=

password:

fafafafa

The Dart code produces an exception:

Unhandled exception:
Invalid argument(s): Invalid or corrupted pad block

,which I suspect happens because in the Dart code, I make use of PKCS7Padding while in my code there is not padding performed on the data.

I am a bit lost, I couldn't find a way to process the data while using salt without unpadding.

If I skip the PaddedBlockCipherImpl and plain call

  CBCBlockCipher cipher = CBCBlockCipher(AESEngine());


    ParametersWithIV<KeyParameter> params =
    ParametersWithIV<KeyParameter>(KeyParameter(key), iv);

    cipher.init(false, params);


    var val = cipher.process(encrypted);
    String res = String.fromCharCodes(val);

    print('res => $res');

I get garbage values.

1 Answer 1

1

You are using the wrong block size in the HMAC - it should be 64 bytes. Change generateKey to this:

Uint8List generateKey(String passphrase, Uint8List salt) {
  final derivator = PBKDF2KeyDerivator(HMac(SHA1Digest(), 64))
    ..init(Pbkdf2Parameters(salt, 1024, 16));
  return derivator.process(utf8.encode(passphrase) as Uint8List);
}

It's tidier to create the cipher in a few lines like this:

  final cipher = PaddedBlockCipherImpl(
    PKCS7Padding(),
    CBCBlockCipher(AESEngine()),
  )..init(
    false,
    PaddedBlockCipherParameters(
      ParametersWithIV(KeyParameter(key), iv),
      null,
    ),
  );

  final pt = cipher.process(encrypted);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.