Java加密与dart flutter解密

6qftjkof  于 2023-02-25  发布在  Flutter
关注(0)|答案(1)|浏览(321)

我正在解密一个用java加密的dart文本。下面是java加密的代码。

package aes;

import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class Aes {

    public static void main(String[] args) {
        try {

            String keyString = "1234567890123456";//length of key is 16
            Cipher desCipher = Cipher.getInstance("AES");
            byte[] key = keyString.getBytes("UTF-8");
            MessageDigest sha = MessageDigest.getInstance("SHA-1");
            key = sha.digest(key);
            key = Arrays.copyOf(key, 16); // use only first 128 bit

            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
            desCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

            String plainText = "abcd";

            byte[] text = plainText.getBytes("UTF-8");
            byte[] textencrypted = desCipher.doFinal(text);
            System.out.println("encrypted: " + new String(textencrypted));

        } catch (Exception ex) {
            Logger.getLogger(Aes.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}

Cipher desCipher = Cipher.getInstance("AES");这里没有定义加密的模式。我发现当没有定义模式时,它使用AES/ECB/PKCS5Padding。而且在加密过程中没有使用IV。
我正在迁移java android应用程序到flutter。服务器上的数据是用上面的java代码加密的。现在我不能从服务器上更改所有正在使用的数据。我必须在flutter中解密它才能在flutter应用程序中显示数据。
我正在使用encrypt: ^4.1.0包在dart解密。

Encrypted encryptedText = Encrypted.fromUtf8('ßȶ8)\œå7£');
  final key = Key.fromUtf8('1234567890123456');
  final iv = IV.fromLength(16);

  final encrypter = Encrypter(AES(key, mode: AESMode.ecb));

  final decrypted = encrypter.decrypt(encryptedText, iv: iv);

  print(decrypted);

但此代码会产生如下错误

E/flutter (18070): [ERROR:flutter/lib/ui/ui_dart_state.cc(171)] Unhandled Exception: Invalid argument(s): Input data length must be a multiple of cipher's block size
E/flutter (18070): #0      PaddedBlockCipherImpl.process (package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart:60:9)
E/flutter (18070): #1      AES.decrypt (package:encrypt/src/algorithms/aes.dart:55:22)
E/flutter (18070): #2      Encrypter.decryptBytes (package:encrypt/src/encrypter.dart:25:17)
E/flutter (18070): #3      Encrypter.decrypt (package:encrypt/src/encrypter.dart:31:17)
E/flutter (18070): #4      _MyHomePageState.sha1 (package:flutter_decrypt_video/main.dart:196:33)
E/flutter (18070): #5      _MyHomePageState.build (package:flutter_decrypt_video/main.dart:85:5)
E/flutter (18070): #6      StatefulElement.build (package:flutter/src/widgets/framework.dart:4681:28)
E/flutter (18070): #7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4564:15)
E/flutter (18070): #8      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4737:11)
E/flutter (18070): #9      Element.rebuild (package:flutter/src/widgets/framework.dart:4280:5)
E/flutter (18070): #10     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4543:5)
E/flutter (18070): #11     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4728:11)
E/flutter (18070): #12     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4538:5)
E/flutter (18070): #13     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3508:14)
E/flutter (18070): #14     Element.updateChild (package:flutter/src/widgets/framework.dart:3266:18)
E/flutter (18070): #15     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5892:14)
E/flutter (18070): #16     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3508:14)
E/flutter (18070): #17     Element.updateChild (package:flutter/src/widgets/framework.dart:3266:18)
E/flutter (18070): #18     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4589:16)
E/flutter (18070): #19     Element.rebuild (package:flutter/src/widgets/framework.dart:4280:5)
E/flutter (18070): #20     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4543:5)
E/flutter (18070): #21     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4538:5)
E/flutter (18070): #22     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3508:14)
E/flutter (18070): #23     Element.updateChild (package:flutter/src/widgets/framework.dart:3266:18)
E/flutter (18070): #24     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5892:14)
E/flutter (18070): #25     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3508:14)
E/flutter (18070): #26     Element.updateChild (package:flutter/src/widgets/framework.dart:3266:18)
E/flutter (18070): #27     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5892:14)
E/flutter (18070): #28     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3508:14)
E/flutter (18070): #29     Element.updateChild (package:flutter/src/widgets/framework.dart:3266:18)
E/flutter (18070): #30     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4589:16)
E/flutter (18070): #31     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4737:11)
E/flutter (18070): #32     Element.rebuild (package:flutter/src/widgets/framework.dart:4280:5)
E/flutter (18070): #33     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4543:5)
E/flutter (18070): #34     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4728:11)
E/flutter (18070): #35     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4538:5)
E/flutter (18070): #36     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3508:14)
E/flutter (18070): #37     Element.updateChild (package:flutter/src/widgets/framework.dart:3266:18)
E/flutter (18070): #38     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5892:14)
E/flutter (18070): #39     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3508:14)
E/flutter (18070): #40     Element.updateChild (package:flutter/src/widgets/framework.dart:3266:18)
E/flutter (18070): #41     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5892:14)
E/flutter (18070): #42     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3508:14)
E/flutter (18070): #43     Element.updateChild (package:flutter/src/widgets/framework.dart:3266:18)
E/flutter (18070): #44     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4589:16)
E/flutter (18070): #45     StatefulElement.performRebuild (package:flutter/src/widgets/fram

如果有人知道如何做到这一点,请把你的答案。
在用于加密的java代码中,SHA-1散列算法用于获得160位密钥,然后使用前128位进行加密,这是否会导致任何问题?
如果有人知道任何其他软件包可以解决我的问题,请让我知道。
如果任何人想要任何进一步的信息,请让我知道。
提前感谢!!

6jjcrrmo

6jjcrrmo1#

在Java代码中,密文使用字符集编码(如UTF-8)转换为字符串。这通常会破坏数据。这里应该使用base64之类的二进制到文本编码。
问题中公布的Java代码提供了以下更改:

import java.util.Base64;
...
Cipher desCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
...
String plainText = "The quick brown fox jumps over the lazy dog";
...
System.out.println("encrypted: " + Base64.getEncoder().encodeToString(textencrypted));
...

以下Base64编码的密文:

encrypted: Mj48sRIlEidcVHVHIw8i8PPXUQiZB3toykI7ODbzXvbrFyOO957Euy0mzgfbVGVF

此密文可以使用Pointy Castle包和以下Dart代码进行解密:

import 'dart:convert';
import 'dart:typed_data';
import 'package:pointycastle/api.dart';
import 'package:pointycastle/block/aes_fast.dart';
import 'package:pointycastle/block/modes/ecb.dart';
import 'package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart';
import 'package:pointycastle/paddings/pkcs7.dart';
...
Digest sha1 = Digest("SHA-1");
Uint8List key = sha1.process(utf8.encode('1234567890123456')).sublist(0, 16);
Uint8List ciphertext = base64.decode('Mj48sRIlEidcVHVHIw8i8PPXUQiZB3toykI7ODbzXvbrFyOO957Euy0mzgfbVGVF');
ECBBlockCipher cipher = ECBBlockCipher(AESFastEngine());
PaddedBlockCipher paddedCipher = new PaddedBlockCipherImpl(new PKCS7Padding(), cipher);
PaddedBlockCipherParameters<CipherParameters, CipherParameters> paddingParams = new PaddedBlockCipherParameters(KeyParameter(key), null);
paddedCipher.init(false, paddingParams);
Uint8List plainText = paddedCipher.process(ciphertext);
print(utf8.decode(plainText));

请注意以下事项:ECB是一种不安全的模式。更安全的是CBC(参见here的dart示例)或GCM,后者允许加密以及数据验证。此外,使用SHA-1从密码导出密钥也是不安全的。这里应该使用可靠的密钥导出函数,例如PBKDF2。

    • 编辑:**

将密文转换为字符集为UTF-8的字符串会损坏数据。你可以在Stackoverflow上找到很多帖子,例如this one,它详细解释了这个问题。这意味着如果密文转换为UTF-8,你问题中的Java代码将无法 * 可靠地 * 工作。
但是,有些字符集(如ISO-8859 - 1)不会损坏数据。服务器上可能使用了此类字符集。这无法从发送的代码中确定,因为在解码过程中未指定字符集(即new String(textencrypted)),因此应用相应平台的默认字符集,请参见此处。因此,要检查这种可能性,你必须确定在服务器上使用哪个默认字符集。
另一种分析使用哪种编码的方法是检查(或发布)用于解密服务器创建的密文的代码。
最可靠的是使用专门用于将二进制数据转换为字符串的编码,即所谓的二进制到文本编码,如Base64,请参见here,这就是我在发布的示例中使用Base64的原因。
您可以使用以下Java代码验证使用UTF-8或ISO-8859 - 1进行转换的效果。上面示例中的数据用作密文:

convertDataWith(StandardCharsets.UTF_8);
convertDataWith(StandardCharsets.ISO_8859_1);
...
private static void convertDataWith(Charset charset) {
    String ciphertextBeforeB64 = "Mj48sRIlEidcVHVHIw8i8PPXUQiZB3toykI7ODbzXvbrFyOO957Euy0mzgfbVGVF";    // Data from posted example
    byte[] ciphertextBefore = Base64.getDecoder().decode(ciphertextBeforeB64);
    String ciphertextCharset = new String(ciphertextBefore, charset);                                   // Convert to String with specified charset
    byte[] ciphertextAfter = ciphertextCharset.getBytes(charset);                                       // Convert from String with specified charset
    String ciphertextAfterB64 = Base64.getEncoder().encodeToString(ciphertextAfter);
    System.out.println("Ciphertext BEFORE conversion: " + ciphertextBeforeB64);
    System.out.println("Ciphertext AFTER conversion:  " + ciphertextAfterB64);  
}

其输出为:

Ciphertext BEFORE conversion: Mj48sRIlEidcVHVHIw8i8PPXUQiZB3toykI7ODbzXvbrFyOO957Euy0mzgfbVGVF
Ciphertext AFTER conversion:  Mj4877+9EiUSJ1xUdUcjDyLvv73vv73vv71RCO+/vQd7aO+/vUI7ODbvv71e77+977+9FyPvv73vv73vv73Euy0m77+9B++/vVRlRQ==

Ciphertext BEFORE conversion: Mj48sRIlEidcVHVHIw8i8PPXUQiZB3toykI7ODbzXvbrFyOO957Euy0mzgfbVGVF
Ciphertext AFTER conversion:  Mj48sRIlEidcVHVHIw8i8PPXUQiZB3toykI7ODbzXvbrFyOO957Euy0mzgfbVGVF

如上所述,UTF-8会破坏数据。

相关问题