Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5.0.2 cannot decrypt data encoded with 5.0.1 #314

Open
alextekartik opened this issue Sep 15, 2023 · 37 comments
Open

5.0.2 cannot decrypt data encoded with 5.0.1 #314

alextekartik opened this issue Sep 15, 2023 · 37 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@alextekartik
Copy link

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 !

@ClevertonZarelli

This comment was marked as duplicate.

@aldycool
Copy link

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

@alessandrorisse

This comment was marked as duplicate.

@leocavalcante
Copy link
Owner

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

@abinvs-2019

This comment was marked as duplicate.

@remsysinc
Copy link

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.

@idoamram

This comment was marked as duplicate.

1 similar comment
@mihaieremia

This comment was marked as duplicate.

@heshesh2010

This comment was marked as duplicate.

@heshesh2010
Copy link

pointycastle

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

@hotplato

This comment was marked as duplicate.

@ivofernandes

This comment was marked as duplicate.

@leocavalcante
Copy link
Owner

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

@Constans

This comment was marked as duplicate.

@ClevertonZarelli
Copy link

still with error

@leocavalcante
Copy link
Owner

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?

@lyskouski
Copy link

lyskouski commented Sep 18, 2023

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>

@leocavalcante leocavalcante added bug Something isn't working help wanted Extra attention is needed labels Sep 18, 2023
@leocavalcante
Copy link
Owner

The same problem with the latest 5.0.3 version

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

Help wanted.

@Constans
Copy link

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).

@leocavalcante
Copy link
Owner

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.

@lyskouski
Copy link

lyskouski commented Sep 18, 2023

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

@leocavalcante
Copy link
Owner

I mean: the downgrade of the Pointycastle...

@leocavalcante
Copy link
Owner

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

@ramvenkat11

This comment was marked as duplicate.

@ClevertonZarelli
Copy link

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.

@mehdiwaysi

This comment was marked as duplicate.

@alextekartik
Copy link
Author

alextekartik commented Sep 21, 2023

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?

@leocavalcante
Copy link
Owner

leocavalcante commented Sep 21, 2023

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?

@alextekartik
Copy link
Author

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.

@moodstubos
Copy link

moodstubos commented Oct 6, 2023

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).

@fede1295
Copy link

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

@mminhlequang
Copy link

up

cw-JihunCha added a commit to cw-JihunCha/encrypt that referenced this issue Mar 4, 2024
@vihangel
Copy link

vihangel commented Mar 7, 2024

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

@alextekartik
Copy link
Author

@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.

@Chakib-Temal
Copy link

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

@BheemrajS
Copy link

BheemrajS commented May 3, 2024

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

@mikezander
Copy link

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;
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests