如何在 dart 中使用 AES CBC 256 位和 PKCS5Padding 进行加密和解密并检索参数
How to encrypt and decrypt using AES CBC 256bit and PKCS5Padding in dart and also retrieve parameters
我有一些 java 代码想在 Dart 中复制(class 可以在 here 找到)
/**
* Encrypt object with password
* @param data Object to be encrypted
* @param secret Password to use for encryption
* @return Encrypted version of object
*/
public static EncryptedBytes encrypt(String data, SecretKey secret) throws InvalidKeyException {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
// properly encode the complete ciphertext
//logEncrypt(password, object);
byte[] encodedData = cipher.doFinal(Base64.getEncoder().encode(data.getBytes(Charset.forName("UTF-8"))));
byte[] params = cipher.getParameters().getEncoded();
String paramAlgorithm = cipher.getParameters().getAlgorithm();
return new EncryptedBytes(encodedData, params, paramAlgorithm);
} catch (NoSuchAlgorithmException | IllegalBlockSizeException | NoSuchPaddingException | BadPaddingException | IOException e) {
e.printStackTrace();
}
return null;
}
/**
* Decrypt data with secret
* @param encryptedBytes Object to be decrypted
* @param secret Password to use for decryption
* @return Decrypted version of object
*/
public static String decrypt(EncryptedBytes encryptedBytes, @NonNull SecretKey secret) throws InvalidKeyException {
try {
// get parameter object for password-based encryption
AlgorithmParameters algParams = AlgorithmParameters.getInstance(encryptedBytes.getParamAlgorithm());
// initialize with parameter encoding from above
algParams.init(encryptedBytes.getParams());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, algParams);
return new String(Base64.getDecoder().decode(cipher.doFinal(encryptedBytes.getData())), Charset.forName("UTF-8"));
} catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | IOException | InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
EncryptedBytes class 只是一个数据持有者
@RequiredArgsConstructor
@Getter
public class EncryptedBytes {
private final byte[] data;
private final byte[] params;
private final String paramAlgorithm;
}
现在在 Dart 中,我正在使用 PointyCastle 并且已经接近(虽然没有测试)
static EncryptedBytes encrypt(String data, KeyParameter keyParameter) {
final AESFastEngine aes = AESFastEngine()..init(false, keyParameter); // false=decrypt
Uint8List encryptedData = aes.process(utf8.encode(data)); // Needs to convert to UTF8 then Base64 and finally be encrypted
Uint8List params;
String algorithm = aes.algorithmName;
return EncryptedBytes(encryptedData, params, algorithm);
}
static String decrypt(EncryptedBytes data, KeyParameter keyParameter) {
final AESFastEngine aes = AESFastEngine()..init(true, keyParameter); // true=encrypt
String encryptedData = utf8.decode(aes.process(data.data)); // Needs to be decrypted, then decoded from Base64 and finally UTF8
return encryptedData;
}
我不完全确定我可以使用什么在 Dart 中获得与上述 java 代码等效的代码。 Base64 returns 一个用于编码的字符串,需要一个用于解码的字符串,而 aes.process() 需要和 returns Uint8List
这是一个在 Java 中编码,在 pointycastle 中解码的工作示例。
Java
String plainText = "Hello World!";
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256);
SecretKey secret = generator.generateKey();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] encodedData = cipher.doFinal(Base64.getEncoder().encode(plainText.getBytes(StandardCharsets.UTF_8)));
Base64.Encoder encoder = Base64.getEncoder();
System.out.println(encoder.encodeToString(secret.getEncoded()));
System.out.println(encoder.encodeToString(cipher.getParameters().getEncoded())); // the DER encoded IV
System.out.println(encoder.encodeToString(encodedData));
飞镖
import 'dart:convert';
import 'dart:typed_data';
import 'package:pointycastle/export.dart';
void main() {
// the following 3 values were output from the above Java code
var key = base64.decode('9JYmap3xB79oyBkY6ZIdJCXaOr/CurCK8XUsRZL9XXI=');
var params = base64.decode('BBChkSMIq/v35PRRWAJGwtTr');
var cipherText =
base64.decode('Dh+lg2IMzcLC0toDRSoNMAQoR7MWKMLMPRi7KtdQdmw=');
var iv = params.sublist(2); // strip the 4, 16 DER header
var cipher = PaddedBlockCipherImpl(
PKCS7Padding(),
CBCBlockCipher(AESFastEngine()),
);
cipher.init(
false /*decrypt*/,
PaddedBlockCipherParameters<CipherParameters, CipherParameters>(
ParametersWithIV<KeyParameter>(KeyParameter(key), iv),
null,
),
);
var plainishText = cipher.process(cipherText);
print(utf8.decode(base64.decode(utf8.decode(plainishText))));
}
在 Dart 中加密
var key = Uint8List(32); // the 256 bit key
var plainText = 'Ciao Mondo';
var random = Random.secure();
var params = Uint8List(18)
..[0] = 4
..[1] = 16;
for (int i = 2; i < 18; i++) {
params[i] = random.nextInt(256);
}
var iv = params.sublist(2);
var cipher = PaddedBlockCipherImpl(
PKCS7Padding(),
CBCBlockCipher(AESFastEngine()),
)..init(
true /*encrypt*/,
PaddedBlockCipherParameters<CipherParameters, CipherParameters>(
ParametersWithIV<KeyParameter>(KeyParameter(key), iv),
null,
),
);
var plainBytes = utf8.encode(base64.encode(utf8.encode(plainText)));
var cipherText = cipher.process(plainBytes);
// cipherText is the cipher text
// params is the Java compatible params
我有一些 java 代码想在 Dart 中复制(class 可以在 here 找到)
/**
* Encrypt object with password
* @param data Object to be encrypted
* @param secret Password to use for encryption
* @return Encrypted version of object
*/
public static EncryptedBytes encrypt(String data, SecretKey secret) throws InvalidKeyException {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
// properly encode the complete ciphertext
//logEncrypt(password, object);
byte[] encodedData = cipher.doFinal(Base64.getEncoder().encode(data.getBytes(Charset.forName("UTF-8"))));
byte[] params = cipher.getParameters().getEncoded();
String paramAlgorithm = cipher.getParameters().getAlgorithm();
return new EncryptedBytes(encodedData, params, paramAlgorithm);
} catch (NoSuchAlgorithmException | IllegalBlockSizeException | NoSuchPaddingException | BadPaddingException | IOException e) {
e.printStackTrace();
}
return null;
}
/**
* Decrypt data with secret
* @param encryptedBytes Object to be decrypted
* @param secret Password to use for decryption
* @return Decrypted version of object
*/
public static String decrypt(EncryptedBytes encryptedBytes, @NonNull SecretKey secret) throws InvalidKeyException {
try {
// get parameter object for password-based encryption
AlgorithmParameters algParams = AlgorithmParameters.getInstance(encryptedBytes.getParamAlgorithm());
// initialize with parameter encoding from above
algParams.init(encryptedBytes.getParams());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, algParams);
return new String(Base64.getDecoder().decode(cipher.doFinal(encryptedBytes.getData())), Charset.forName("UTF-8"));
} catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | IOException | InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
EncryptedBytes class 只是一个数据持有者
@RequiredArgsConstructor
@Getter
public class EncryptedBytes {
private final byte[] data;
private final byte[] params;
private final String paramAlgorithm;
}
现在在 Dart 中,我正在使用 PointyCastle 并且已经接近(虽然没有测试)
static EncryptedBytes encrypt(String data, KeyParameter keyParameter) {
final AESFastEngine aes = AESFastEngine()..init(false, keyParameter); // false=decrypt
Uint8List encryptedData = aes.process(utf8.encode(data)); // Needs to convert to UTF8 then Base64 and finally be encrypted
Uint8List params;
String algorithm = aes.algorithmName;
return EncryptedBytes(encryptedData, params, algorithm);
}
static String decrypt(EncryptedBytes data, KeyParameter keyParameter) {
final AESFastEngine aes = AESFastEngine()..init(true, keyParameter); // true=encrypt
String encryptedData = utf8.decode(aes.process(data.data)); // Needs to be decrypted, then decoded from Base64 and finally UTF8
return encryptedData;
}
我不完全确定我可以使用什么在 Dart 中获得与上述 java 代码等效的代码。 Base64 returns 一个用于编码的字符串,需要一个用于解码的字符串,而 aes.process() 需要和 returns Uint8List
这是一个在 Java 中编码,在 pointycastle 中解码的工作示例。
Java
String plainText = "Hello World!";
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256);
SecretKey secret = generator.generateKey();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] encodedData = cipher.doFinal(Base64.getEncoder().encode(plainText.getBytes(StandardCharsets.UTF_8)));
Base64.Encoder encoder = Base64.getEncoder();
System.out.println(encoder.encodeToString(secret.getEncoded()));
System.out.println(encoder.encodeToString(cipher.getParameters().getEncoded())); // the DER encoded IV
System.out.println(encoder.encodeToString(encodedData));
飞镖
import 'dart:convert';
import 'dart:typed_data';
import 'package:pointycastle/export.dart';
void main() {
// the following 3 values were output from the above Java code
var key = base64.decode('9JYmap3xB79oyBkY6ZIdJCXaOr/CurCK8XUsRZL9XXI=');
var params = base64.decode('BBChkSMIq/v35PRRWAJGwtTr');
var cipherText =
base64.decode('Dh+lg2IMzcLC0toDRSoNMAQoR7MWKMLMPRi7KtdQdmw=');
var iv = params.sublist(2); // strip the 4, 16 DER header
var cipher = PaddedBlockCipherImpl(
PKCS7Padding(),
CBCBlockCipher(AESFastEngine()),
);
cipher.init(
false /*decrypt*/,
PaddedBlockCipherParameters<CipherParameters, CipherParameters>(
ParametersWithIV<KeyParameter>(KeyParameter(key), iv),
null,
),
);
var plainishText = cipher.process(cipherText);
print(utf8.decode(base64.decode(utf8.decode(plainishText))));
}
在 Dart 中加密
var key = Uint8List(32); // the 256 bit key
var plainText = 'Ciao Mondo';
var random = Random.secure();
var params = Uint8List(18)
..[0] = 4
..[1] = 16;
for (int i = 2; i < 18; i++) {
params[i] = random.nextInt(256);
}
var iv = params.sublist(2);
var cipher = PaddedBlockCipherImpl(
PKCS7Padding(),
CBCBlockCipher(AESFastEngine()),
)..init(
true /*encrypt*/,
PaddedBlockCipherParameters<CipherParameters, CipherParameters>(
ParametersWithIV<KeyParameter>(KeyParameter(key), iv),
null,
),
);
var plainBytes = utf8.encode(base64.encode(utf8.encode(plainText)));
var cipherText = cipher.process(plainBytes);
// cipherText is the cipher text
// params is the Java compatible params