在 Java 中加密并在 dart flutter 中解密 [英] Encrypted in Java and Decrypting in dart flutter

查看:30
本文介绍了在 Java 中加密并在 dart flutter 中解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 dart 解密用 Java 加密的文本.下面是用于加密的java代码.

I am decrypting a text in dart which is encrypted in java. Here is the code of java which is used for encryption.

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.

Cipher desCipher = Cipher.getInstance("AES"); here mode of encryption is not defined. I found that when mode is not defined it uses AES/ECB/PKCS5Padding. Also IV is not used during encryption.

我正在将 java android 应用程序迁移到 flutter.服务器上的数据使用上述 java 代码加密.现在我无法从服务器更改所有正在使用的数据.我必须在flutter中解密它才能在flutter app中显示数据.

I am migrating the java android application to flutter. data on the server is encrypted using this above java code. Now I can't change the all the in use data from the server. I have to decrypt it in flutter to show the data in flutter app.

我正在使用 encrypt: ^4.1.0 包在 dart 中进行解密.

I am using encrypt: ^4.1.0 package for decryption in 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

如果有人知道怎么做,请给出你的答案.

If anyone know how to do this please put your answer.

在用于加密的java代码中,SHA-1哈希算法用于获取160位密钥,然后使用前128位进行加密,这会导致什么问题吗?

In java code which is used for encryption SHA-1 hashing algorithm is used to get 160 bit of key and then it uses first 128 bits for encryption, may it causes any problem?

如果有人知道可以解决我的问题的其他软件包,请告诉我.

If anyone knows any another package which can solve my issue please let me know.

如果有人想了解更多信息,请告诉我.

If anyone want any further information please let me know.

提前致谢!!

推荐答案

在 Java 代码中,密文使用字符集编码(如 UTF-8)转换为字符串.这通常会损坏数据.这里应该使用像 base64 这样的二进制到文本编码.

In the Java code, the ciphertext is converted into a string using a charset encoding (like UTF-8). This generally corrupts the data. Here a binary-to-text encoding like base64 should be used.

问题中发布的 Java 代码提供了以下更改:

The Java code posted in the question provides with the following changes:

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 编码密文:

the following Base64 encoded ciphertext:

encrypted: Mj48sRIlEidcVHVHIw8i8PPXUQiZB3toykI7ODbzXvbrFyOO957Euy0mzgfbVGVF

可以使用带有以下 Dart 代码的 Pointy Castle 包解密此密文:

This ciphertext can be decrypted using the Pointy Castle package with the following Dart code:

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(参见此处了解 dart 示例)或 GCM,后者允许加密和数据身份验证.此外,从具有 SHA-1 的密码派生密钥也是不安全的.这里有一个可靠的密钥派生函数,例如应该使用PBKDF2.

Please note the following: ECB is an insecure mode. More secure are CBC (see here for a dart example) or GCM, where the latter allows encryption as well as data authentication. Also the derivation of a key from a password with SHA-1 is insecure. Here a reliable key derivation function, e.g. PBKDF2, should be used.


将密文转换为带有像 UTF-8 这样的字符集的字符串会损坏数据.你可以在 Stackoverflow 上找到很多帖子,例如这个,详细解释了问题.这意味着如果使用 UTF-8 转换密文,您问题中发布的 Java 代码将无法可靠工作.


Converting a ciphertext into a string with a charset like UTF-8 will damage the data. You can find many posts on Stackoverflow, e.g. this one, which explains the problem in detail. This means that the Java code posted in your question won't work reliably if the ciphertext is converted with UTF-8.

但是,有像 ISO-8859-1 这样的字符集不会破坏数据.有可能在服务器上使用这样的字符集.这不能从发布的代码中确定,因为在解码过程中没有指定字符集(即在 new String(textencrypted) 中),因此应用了相应平台的默认字符集,请参阅 此处.因此,要检查这种可能性,您必须确定服务器上使用的是哪个默认字符集.
另一种分析使用哪种编码的方法是检查(或发布)用于解密服务器创建的密文的代码.

However, there are charsets like ISO-8859-1 that do not corrupt the data. It is possible that such a charset is used on the server. This cannot be determined from the posted code, because no charset is specified during decoding (i.e. in new String(textencrypted)), so the default charset of the respective platform is applied, see here. Therefore, to check this possibility, you have to determine which default charset is used on the server.
Another way to analyze which encoding is used would be to check (or post) the code that is used to decrypt the ciphertext created by the server.

最可靠的是使用专用于将二进制数据转换为字符串的编码,即所谓的二进制到文本编码,例如 Base64,请参阅 此处,这就是我在发布的示例中使用 Base64 的原因.

Most reliable is the use of encodings that are dedicated to convert binary data into a string, so called binary-to-text encodings, such as Base64, see here, which is why I used Base64 in the posted example.

您可以使用以下 Java 代码验证使用 UTF-8 或 ISO-8859-1 的转换效果.上面发布的示例中的数据用作密文:

You can verify the effects of a conversion using UTF-8 or ISO-8859-1 with the following Java code. The data from the posted example above is used as ciphertext:

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 会损坏数据.

As explained above, UTF-8 corrupts the data.

这篇关于在 Java 中加密并在 dart flutter 中解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆