gpt4 book ai didi

java - 在 Dart 中解密 Java AES 编码的字符串

转载 作者:行者123 更新时间:2023-11-30 01:46:08 24 4
gpt4 key购买 nike

我需要在 Flutter 移动应用程序中解密 AES (PKCS#7) 编码的字符串。

该字符串是从 QR 码中获取的,该 QR 码是从 Java 应用程序生成的,包含 AES 编码的字符串。

Java 编码:

import java.security.Security;
import java.nio.charset.StandardCharsets;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class MyClass {

public static void main(String[] args) throws Exception {
String toEncode = "firstname.lastname@mycompany.com;12";
String encoded = pleaseEncodeMe(toEncode);
System.out.println(encoded);
}

private static String pleaseEncodeMe(String plainText) throws Exception {
Security.addProvider(new BouncyCastleProvider());
final String encryptionAlgorithm = "AES/CBC/PKCS7PADDING";
final String encryptionKey = "WHatAnAWEsoMeKey";
final SecretKeySpec keySpecification = new SecretKeySpec(encryptionKey.getBytes(StandardCharsets.UTF_8), encryptionAlgorithm);
final Cipher cipher = Cipher.getInstance(encryptionAlgorithm, "BC");
cipher.init(Cipher.ENCRYPT_MODE, keySpecification);
final byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
return Base64.encodeBase64URLSafeString(encryptedBytes);
}

}

输出:AIRTEuNmSuQtYuysv93w3w83kJJ6sg7kaU7XzA8xrAjOp-lKYPp1brtDAPbhSJmT

Dart 解码:

void main() {
print(decodeMeOrDie("AIRTEuNmSuQtYuysv93w3w83kJJ6sg7kaU7XzA8xrAjOp-lKYPp1brtDAPbhSJmT"));
}

String decodeMeOrDie(String encryptedString) {
final key = Key.fromUtf8("WHatAnAWEsoMeKey");
final iv = IV.fromLength(16);
final encrypter = Encrypter(AES(key, mode: AESMode.cbc, padding: "PKCS7"));
return encrypter.decrypt64(encryptedString, iv: iv);
}

输出:Y��=X�Rş �"Qme@mycompany.com;12

您可以看到只解码了字符串的一部分。

最佳答案

  • 必须考虑两件事:

    1) 对于解密,需要用于加密的IV。

    2) 出于安全原因,必须为每次加密随机生成一个新的 IV,以便同一 key here 不会多次使用 IV。 。

    因此,IV必须从加密端传递到解密端。这不会自动发生,而是必须实现。

  • 一种可能性是连接 IV 和密文的字节数组。通常 IV 放在密文之前,结果是 Base64 编码的(如果需要),例如在Java中:

    // Concatenate IV and ciphertext
    byte[] iv = ...
    byte[] ciphertext = ...
    byte[] ivAndCiphertext = new byte[iv.length + ciphertext.length];
    System.arraycopy(iv, 0, ivAndCiphertext, 0, iv.length);
    System.arraycopy(ciphertext, 0, ivAndCiphertext, iv.length, ciphertext.length);
    // If required: Base64-encoding

    该数据被传输到解密端,解密端在 Base64 解码后将两部分分开。在 AES-CBC 的情况下,IV 的长度为 16 个字节,因此前 16 个字节代表 IV,其余的为密文。 IV 不需要加密,因为它不是 secret 的。

    特别对于您的情况,这意味着您必须在 Java 端连接 IV 和密文并对结果进行 Base64 编码。在 Dart 端,您必须先进行 Base64 解码,然后才能将 IV 和密文这两个部分分开并用于以下解密。

  • 加密前生成 IV 的方法有两种: 通过 Cipher 隐式生成-实例如您的示例或显式生成,例如通过SecureRandom 。讨论了两种替代方案 here 。如果 IV 是隐式生成的(通过 Cipher 实例),则必须通过 Cipher 实例确定该 IV,因为稍后解密需要它:

    // Determine IV from cipher for later decryption
    byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();

    如果 IV 是显式确定的(例如使用 SecureRandom),则必须将其传递到 Cipher 实例,以便在运行的加密中使用它。这是使用 IvParameterSpec 完成的.

    // Assign IV to cipher so that it is used for current encryption
    byte[] iv = ...
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
    cipher.init(Cipher.ENCRYPT_MODE, secretkeySpec, ivParameterSpec);
  • 硬编码 key 通常不是一个好的做法(也许除了测试目的)。但是, key 生成/管理的主题超出了本答案的范围。关于这个主题已经有很多问题和答案。如果这些答案未涵盖您的问题,请发布新问题。硬编码 IV 不会出现在上述架构中,并且只能用于测试目的。

<小时/>

关于java - 在 Dart 中解密 Java AES 编码的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57892036/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com