leocavalcante / encrypt

đź”’ A set of high-level APIs over PointyCastle for two-way cryptography.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

5.0.2 cannot decrypt data encoded with 5.0.1

alextekartik opened this issue · comments

I get different results since upgrading to 5.0.2. The following test:

import 'package:encrypt/encrypt.dart';
import 'package:test/test.dart';

String encrypt(String decoded, String password) {
  final key = Key.fromUtf8(password);
  final iv = IV.fromLength(16);
  final encrypter = Encrypter(AES(key));
  return encrypter.encrypt(decoded, iv: iv).base64;
}

String decrypt(String encoded, String password) {
  final key = Key.fromUtf8(password);
  final iv = IV.fromLength(16);
  final encrypter = Encrypter(AES(key));
  return encrypter.decrypt(Encrypted.fromBase64(encoded), iv: iv);
}

void main() {
  test('AES encrypt/decrypt', () {
    var password = r'E4x*$TwbkJC-xK4KGC4zJF9j*Rh&WLgR';
    expect(decrypt('amGhyRRLUIoE59IiEys5Vw==', password), 'test');
  });
}

works fine with 5.0.1 but fails with 5.0.2.

package:pointycastle/paddings/pkcs7.dart 42:7                                  PKCS7Padding.padCount
package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart 112:30  PaddedBlockCipherImpl.doFinal
package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart 74:25   PaddedBlockCipherImpl.process
package:encrypt/src/algorithms/aes.dart 68:22                                  AES.decrypt
package:encrypt/src/encrypter.dart 39:10                                       Encrypter.decryptBytes
package:encrypt/src/encrypter.dart 50:7                                        Encrypter.decrypt
test/aes_test.dart 15:20                                                       decrypt
test/aes_test.dart 21:12                                                       main.<fn>

Invalid argument(s): Invalid or corrupted pad block

Am I using it wrong ? Unfortunately I have some encrypted content that I cannot read anymore.
Thanks !

following, i have the same problem after update

commented

Hi, same here. In the mean time I just use hard-coded version in pubspec.yaml: encrypt: 5.0.1 (without ^).

Same problem

Can you folks force pointycastle: 3.6.2 to see if it works again, please?

Same here.

Same, but it's 5.0.2 that is causing the issue. Reverting to 5.0.1 puts things back in order. Interesting gap in updates as 5.0.1 was 2 years ago; 5.0.2 just two days. Great package and hope this gets resolved. Unsure of what (breaking) changes this update provides.

Same issue

Same issue

pointycastle

I overridden to (pointycastle: 3.6.2) and still got same error

I have the same problem

Same here:

flutter: ^[[38;5;196m[E]^[[0m zoneGuarded: zoneError ERROR: Invalid argument(s): Invalid or corrupted pad b<…>
flutter: #0 PKCS7Padding.padCount (package:pointycastle/paddings/pkcs7.dart:42:7)
#1 PaddedBlockCipherImpl.doFinal (package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart:112:30)
#2 PaddedBlockCipherImpl.process (package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart:74:25)
#3 AES.decrypt (package:encrypt/src/algorithms/aes.dart:68:22)
#4 Encrypter.decryptBytes (package:encrypt/src/encrypter.dart:39:10)
#5 Encrypter.decrypt (package:encrypt/src/encrypter.dart:50:7)
#6 EncryptionWrapper.decrypt

Can you guys force pointycastle: 3.2.0? I think that is the one at the previous version.

still with error

The weird thing is that the files on the stacktrace hasn't changed at those spots:

package:encrypt/src/algorithms/aes.dart 68:22
package:encrypt/src/encrypter.dart 39:10
package:encrypt/src/encrypter.dart 50:7

Can you guys spot any differences?

The same problem with the latest 5.0.3 version

flutter: [Invalid argument(s): Invalid or corrupted pad block, #0      PKCS7Padding.padCount (package:pointycastle/paddings/pkcs7.dart:42:7)
#1      PaddedBlockCipherImpl.doFinal (package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart:112:30)
#2      PaddedBlockCipherImpl.process (package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart:74:25)
#3      AES.decrypt (package:encrypt/src/algorithms/aes.dart:68:22)
#4      Encrypter.decryptBytes (package:encrypt/src/encrypter.dart:39:10)
#5      Encrypter.decrypt (package:encrypt/src/encrypter.dart:50:7)
#6      Encrypter.decrypt64 (package:encrypt/src/encrypter.dart:66:12)
<asynchronous suspension>

The same problem with the latest 5.0.3 version

5.0.3 fixes another bug. This one wasn't spotted yet.

Help wanted.

The weird thing is that what was encrypted with 5.0.2 or 5.0.3 can't be decrypted by the same version of the package (also retroactively - something encrypted with 5.0.1). 5.0.1 can't decode something encoded with 5.0.2 or 5.0.3. The reason is the same mentioned here: #314 (comment). Maybe there is a difference in the Initialization Vector (IV).

That is why I think it something at Pointcastle, there wasn't any significative changes at Encrypt, but people are saying that de downgrade didn't work.

Downgrade back to 5.0.1 has helped (with encrypted data by 5.0.3 loss)

I mean: the downgrade of the Pointycastle...

@farukprogrammer do you know if #259 does have something with that somehow?

Downgrade back to 5.0.1 and clear all data that was encrypted in others version, if you use shared preferences, change the version to automatic clear that.
and it back work on this way.

I get this error when decrypt data:

Invalid argument(s): Invalid or corrupted pad block

I didn't have this problem before in version 5.0.1. And recently this problem has arisen.

I updated the package to 5.0.2 , 5.0.3 and have the same error

In my specific issue, it turns out that replacing:

final iv = IV.fromLength(16);

by

final iv = IV.allZerosOfLength(16);

fixes my test. i.e. the following test works fine using 5.0.3:

import 'package:encrypt/encrypt.dart';
import 'package:test/test.dart';

String aesEncrypt(String decoded, String password) {
  final key = Key.fromUtf8(password);
  // final iv = IV.fromLength(16); (ok in 5.0.1 not in 5.0.3)
  final iv = IV.allZerosOfLength(16);
  final encrypter = Encrypter(AES(key));
  return encrypter.encrypt(decoded, iv: iv).base64;
}

String aesDecrypt(String encoded, String password) {
  final key = Key.fromUtf8(password);
  // final iv = IV.fromLength(16); (ok in 5.0.1 not in 5.0.3)
  final iv = IV.allZerosOfLength(16);
  final encrypter = Encrypter(AES(key));
  return encrypter.decrypt(Encrypted.fromBase64(encoded), iv: iv);
}

void main() {
  test('AES encrypt/decrypt', () {
    var password = r'E4x*$TwbkJC-xK4KGC4zJF9j*Rh&WLgR';
    expect(aesEncrypt('test', password), 'amGhyRRLUIoE59IiEys5Vw==');
    expect(aesDecrypt('amGhyRRLUIoE59IiEys5Vw==', password), 'test');
  });
}

So it seems that the behavior of IV.fromLength() has changed between the 5.0.1 version (filling with 0) and 5.0.3 (filling with random characters.) Maybe this could be considered as a breaking change as it breaks existing code!

EDIT: The following is compatible for both version:

final iv = IV(Uint8List(16));

However reading the comment:

/// The key is ALL ZEROS - NOT CRYPTOGRAPHICALLY SECURE!
IV.allZerosOfLength(int length)

it sounds that it is not fully secure to use this. What is the correct way to encrypt a content that we need to decrypt later then?. Do we need to save also the content of the iv variable to have it for decryption later?

Hi, @alextekartik.
Thank you very much for digging into this.

Ideally, the Initialization Vector should be secured as well:
https://en.wikipedia.org/wiki/Initialization_vector

After an issue (#246) opened by @InnovativeInventor warning about fromLength implementation being insecure (despite its use was never meant to production, only for tests), @timmaffett helped us (and thanks again for that) solving it at #266.

@deskangel warned us about this risk at #266 (comment) and people was asking for the changes: #295

Meanwhile I haven't been working with Dart/Flutter anymore, I wasn't using this lib and the support was dropping.
I had even renewed my PC and there is nothing of a Dart environment installed, but @JimWuerch helped me at #310 on how I could automate the package publishing and voilá.

I assume it is all my fault, I thought that was just a matter of sending a new release and haven't looked carefully to check for breaking changes. My bad, not an excuse, but is really hard to maintain OSS already, then alone and in a stack that you don't work for years, is even harder.


Thank you all for you patience. I'd love to hear especially from you guys that use the package, how we can go from there:

  • Should we move to a major 6.x?
  • You guys just fix with IV.allZerosOfLength(int length)?
  • Any other suggestions?

Thanks for the support, I know maintaining open source project is a pain ! You might want to get other contributors/publishers if you cannot commit to it in the the long term as it seems many people are using it ! So you have to maintain it forever, ha ha.

Hard to change the behavior especially in an API that is shown as an example in the README.md.

The safest behavior would be to add a new IV.randomOfLength() API (or whatever better naming), keeping the existing behavior of fromLength (filling with 0) or even deprecating it...Personally I'm fine with fixing it on my side although it might require going through many projects.

hi,
@leocavalcante : Thank you very much for you great work!

current state:
Encrypted.fromLength(int length) : _bytes = SecureRandom(length).bytes;
and
Encrypted.fromSecureRandom(int length) : _bytes = SecureRandom(length).bytes;

both (fromLength + from fromSecureRandom) has same implementation. (edit: sorry, not true vor IV)
Therefore, I suggest just leaving the fromLength implementation as the previous one (5.0.1) and deprecating it for 5.1.0. Also change docs to use fromSecureRandom.

Therefore, we don't have a breaking change with a change in the second level version slot (5.0.1 to 5.0.2).

in my case the issue was caused by pointycastle... with encryption at 5.0.1 and pointycastle at version 3.5.2 everything works correctly

I get different results since upgrading to 5.0.2. The following test:

import 'package:encrypt/encrypt.dart';
import 'package:test/test.dart';

String encrypt(String decoded, String password) {
  final key = Key.fromUtf8(password);
  final iv = IV.fromLength(16);
  final encrypter = Encrypter(AES(key));
  return encrypter.encrypt(decoded, iv: iv).base64;
}

String decrypt(String encoded, String password) {
  final key = Key.fromUtf8(password);
  final iv = IV.fromLength(16);
  final encrypter = Encrypter(AES(key));
  return encrypter.decrypt(Encrypted.fromBase64(encoded), iv: iv);
}

void main() {
  test('AES encrypt/decrypt', () {
    var password = r'E4x*$TwbkJC-xK4KGC4zJF9j*Rh&WLgR';
    expect(decrypt('amGhyRRLUIoE59IiEys5Vw==', password), 'test');
  });
}

works fine with 5.0.1 but fails with 5.0.2.

package:pointycastle/paddings/pkcs7.dart 42:7                                  PKCS7Padding.padCount
package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart 112:30  PaddedBlockCipherImpl.doFinal
package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart 74:25   PaddedBlockCipherImpl.process
package:encrypt/src/algorithms/aes.dart 68:22                                  AES.decrypt
package:encrypt/src/encrypter.dart 39:10                                       Encrypter.decryptBytes
package:encrypt/src/encrypter.dart 50:7                                        Encrypter.decrypt
test/aes_test.dart 15:20                                                       decrypt
test/aes_test.dart 21:12                                                       main.<fn>

Invalid argument(s): Invalid or corrupted pad block

Am I using it wrong ? Unfortunately I have some encrypted content that I cannot read anymore. Thanks !

Im facing same issue

I just changed my yaml to
encrypt: 5.0.1

works

@vihangel Being stuck on an old version could be a pain. If you change your existing IV.fromLength to IV.allZerosOfLength you should be fine too on future versions - or even IV(Uint8List(length)) if you want to be compatible with old and new versions of encrypt.

What does this mean? Are we now stuck in version 5.0.1 or what?
@leocavalcante

What does this mean? Are we now stuck in version 5.0.1 or what? @leocavalcante

i had issue when using encrypt version 5.0.2/3 and now i have reverted version to 5.0.1 without "^" prefix as below in pubsepc.xml file. Issue is resolved, encrypt password works.
encrypt: 5.0.1

I'm getting the same error but am not using IV.fromLength. What would be the solution in my case??

  static String decrypt(String s) {
    final e.Key key = e.Key.fromBase64(EnvironmentConfig.encryption_key);
    final e.IV iv = e.IV.fromBase64(EnvironmentConfig.encryption_iv);
    final e.Encrypter encrypter = e.Encrypter(e.AES(key));
    return encrypter.decrypt64(s, iv: iv).toString();
  }

  static String encrypt(String s) {
    final e.Key key = e.Key.fromBase64(EnvironmentConfig.encryption_key);
    final e.IV iv = e.IV.fromBase64(EnvironmentConfig.encryption_iv);
    final e.Encrypter encrypter = e.Encrypter(e.AES(key));
    return encrypter.encrypt(s, iv: iv).base64;
  }