我正在尝试解码之前在 flutter 中加密的 kotlin 中的 Uint8list,但解密不正确,我可能做错了什么但我找不到什么,你能帮我吗?
上下文:
密钥和 IV 目前是常量并且是 128 位,所以 pointyCatle 应该使用 AES128,我应该能够用相同的密钥和 IV 解密它
例子
主键 = 11112222 33344444
Uint8List mainKey = Uint8List.fromList([0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04]);
var SessionCipher=new AESEncryptor();
...
var MainCipher=new AESEncryptor();
MainCipher.setIV(SessionCipher.getIv());
MainCipher.setKey(mainKey);
var encryptedSessionKey = MainCipher.encrypt(SessionCipher.getKey());
和 iv = 00000000 00000000
data 是一个 secureRandom 生成的 Key
两者使用相同的密钥和 IV,均采用 CBC/no-padding
它可能来自使用不同算法的库吗? 我做错了什么吗?
临时Dart加密课
import 'package:ble_connect/utils/ble/FrameBuilder.dart';
import 'package:encrypt/encrypt.dart';
IV newIV() {
// return IV.fromLength(16);
return(IV.fromBase16("00000000000000000000000000000000"));
}
class AESEncryptor {
var iv;
var encrypter;
var key;
AESEncryptor() {
this.key = Key.fromSecureRandom(16);
this.iv = newIV();
this.encrypter = Encrypter(AES(key, mode: AESMode.cbc, padding: null));
}
void setIV(iv) {
this.iv = iv;
}
IV getIv() {
return (this.iv);
}
void setKey(key) {
this.key = key;
}
Key getKey() {
return (this.key);
}
//encrypt method meant to encrypt a 128bits List or 128bits Key
//input : data (Key or Uint8List of length 16)
dynamic encrypt(data) {
print("iv is : ${this.iv.base16}");
if (data.runtimeType == Key) {
data = toInt(combineByTwo(data.base16.split(''))); //convert a Key to a list of bytes (UGLY)
//additional info : data (Key) is converted to hex String by .base16
//then converted to list of char by .split('')
//then the elements of the list are grouped by two (in order to get bytes at the end ex : [f,f]-->[ff]
//finaly parsed to become a list of in values between 0-255
}
return encrypter.encryptBytes(data, iv: this.iv);
}
}
谢谢你的帮助!
编辑: 加密库:https://github.com/leocavalcante/encrypt
Kotlin 代码
private object AES128{
private fun cipher(opmode: Int, secretKey: ByteArray, iv: IvParameterSpec):Cipher{
val c = Cipher.getInstance("AES/CBC/NoPadding")
val sk = SecretKeySpec(secretKey, "AES")
c.init(opmode, sk, iv)
return c
}
fun encrypt(byteArray: ByteArray, secretKey: ByteArray, iv: IvParameterSpec): ByteArray? {
return cipher(Cipher.ENCRYPT_MODE, secretKey, iv).doFinal(padFrame(byteArray))
}
fun decrypt(byteArray: ByteArray, frameDataLength: Int, secretKey: ByteArray, iv: IvParameterSpec):ByteArray?{
return unpadFrame(cipher(Cipher.DECRYPT_MODE, secretKey, iv).doFinal(byteArray), frameDataLength)
}
private fun padFrame(frame: ByteArray): ByteArray {
// MANUAL PADDING
println(frame.size)
val remain = (frame.size % 16).also {
println(it)
}
if (remain != 0) {
println("padding")
val paddedValue = ByteArray(frame.size + 16 - remain)
System.arraycopy(frame, 0, paddedValue, 0, frame.size)
for (i in 0 until 16 - remain) {
paddedValue[frame.size + i] = 0x0F
}
return paddedValue
}
println("not padding")
return frame
}
private fun unpadFrame(frame: ByteArray, frameDataLength: Int): ByteArray {
if(frameDataLength > 5) {
val unpaddedValue = ByteArray(frameDataLength)
System.arraycopy(frame, 0, unpaddedValue, 0, frameDataLength)
return unpaddedValue
}
return frame
}
}
我写了 java 和 dart 一起工作使用 AES CBC 模式 PKCS5 填充 注意 Java 中的 PKCS5 等同于 Dart 中的 PKCS7 - 它们一起工作 你可以在 java 中加密并在 Dart 中解密,反之亦然 这个 Java 部分
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/*********this class to Encrypt and decrypt data used in sending and receiving data**** */
public class Encryptor {
static Encryptor instance = null;
private Encryptor(){
instance=this;
}
final static String AccKey = "ShaniaTwain2023f";
public static void main(String[] args) throws Exception{
//() TODO Auto-generated method stub
String originalString = "I like Shaina Twain Songs";
byte[] ecryptedString =Encryptor.getInstance().encrypt(Encryptor.AccKey, originalString);
String decryptedString = Encryptor.getInstance().decrypt(new String(ecryptedString) , Encryptor.AccKey) ;
}
public byte[] encrypt (String key, String value) {
String encryptString = "";
byte[] keyBytes = new byte[16];
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //1
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");//2
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes); //3
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); //4
encryptString = Base64.getEncoder().encodeToString(cipher.doFinal(value.getBytes("UTF-8")));//5
} catch (Exception e) {
e.printStackTrace();
}
return encryptString.getBytes();
}
public String decrypt (String encrypted , String Key) {
byte[] keyBytes = new byte[16];//1
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");//1
SecretKeySpec skeySpec = new SecretKeySpec(Key.getBytes("UTF-8"), "AES");//2
IvParameterSpec iv = new IvParameterSpec(keyBytes);//3
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);//4
byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted));//5
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Encryptor getInstance() {
// TODO Auto-generated method stub
if (instance==null) {
return new Encryptor();
}else {
return instance;
}
}
}
此 Dart 部分使用 encrypt 5.0.1
import 'dart:typed_data';
import 'package:encrypt/encrypt.dart' as ency;
import 'package:flutter/material.dart';
class Encryptor_ {
static final key = ency.Key.fromUtf8('ShaniaTwain2023f');
static final iv = ency.IV.fromLength(16);
static final encrypter =
ency.Encrypter(ency.AES(key, mode: ency.AESMode.cbc, padding: 'PKCS7'));
static String encrypt(plainText) {
return encrypter.encrypt(plainText, iv: iv).base64.toString();
}
static String decrypt(plainText) {
ency.Encrypted encrypted = ency.Encrypted.from64(plainText);
return encrypter.decrypt(encrypted, iv: iv).toString();
}
}
void main() {
print(Encryptor_.encrypt("Hassan"));
}