leocavalcante / encrypt

🔒 A set of high-level APIs over PointyCastle for two-way cryptography.
BSD 3-Clause "New" or "Revised" License
343 stars 139 forks source link

Why Bad state: IV is required, after upgrade from 4.0.2 to 5.0.0. #211

Open SevenCho opened 3 years ago

SevenCho commented 3 years ago

Upgrade from 4.0.4 to 5.0.0, the original encryption algorithm is wrong。

Mode: ECB Padding: PKCS7 IV: No

    final key = Key(Uint8List.fromList(keyBytes));
    final encrypter = Encrypter(AES(key, mode: AESMode.ecb, padding: 'PKCS7'));
    final encrypted = encrypter.encryptBytes(input);
@override
  Encrypted encrypt(Uint8List bytes, {IV? iv}) {
    if (iv == null) {
      throw StateError('IV is required.');
    }

    if (_streamCipher != null) {
      _streamCipher!
        ..reset()
        ..init(true, _buildParams(iv));

      return Encrypted(_streamCipher!.process(bytes));
    }
leocavalcante commented 3 years ago

@are the ECB mode doesn't require an IV. Do you have fresh in mind why this check? Can I just remove it?

are commented 3 years ago

That was because the _buildParams method uses the ParametersWithIV class that requires iv to be not null, so the check was added to make sure its supplied.

leocavalcante commented 3 years ago

Right, thanks.

@SevenCho can you workaround this by now please giving a meaningless IV?

final encrypted = encrypter.encryptBytes(input, iv: IV.fromLength(16));

I will be thinking on a proper strategy to handle this.

SevenCho commented 3 years ago

Right, thanks.

@SevenCho can you workaround this by now please giving a meaningless IV?

final encrypted = encrypter.encryptBytes(input, iv: IV.fromLength(16));

I will be thinking on a proper strategy to handle this.

Giving a meaningless IV that works. I tried different meaningless IVs. but I don’t know if this will cause potential problems.

final iv = IV.fromBase16("");
final iv = IV.fromLength(16);
leocavalcante commented 3 years ago

Don't worry, for ECB it will just be ignored.

hiashutoshsingh commented 3 years ago

Please fix this, ECB does not require an IV. So supplying an IV should not be required. Also worse is that the function still fails if you provide null, even though signature specifically allows it:

https://pub.dev/documentation/encrypt/latest/encrypt/Encrypter/encrypt.html

but in my case it still giving an error

wbusey0 commented 3 years ago

Right, thanks.

@SevenCho can you workaround this by now please giving a meaningless IV?

final encrypted = encrypter.encryptBytes(input, iv: IV.fromLength(16));

I will be thinking on a proper strategy to handle this.

I think moving the iv == null check into the _buildParams method right before the return would solve this?