Flutter 颤振中的AES加密无法正常工作
我们正在将一个应用程序从本地Android/iOS移植到Flatter。我们在本机应用程序中使用AES对称加密,它们与我们的设备配合良好 下面是我们试图复制java实现的颤振代码 在这里,我们向设备发送客户端(app)公钥和客户端nonce(随机16位)。设备使用设备公钥、客户端公钥和mac id创建一个加密数据包,并在加密后将其发送到应用程序。我们在应用程序上解密接收到的数据包,并在我们这边创建一个类似的数据包,然后匹配这两个数据包 在我们的例子中,它们在Flutter中都是匹配的(这表明我们已经正确地完成了加密过程)。问题是,在这个过程之后,当我们试图通过加密数据向设备发送下一个命令时,设备无法理解它,并使用垃圾数据进行回复Flutter 颤振中的AES加密无法正常工作,flutter,dart,encryption,aes,Flutter,Dart,Encryption,Aes,我们正在将一个应用程序从本地Android/iOS移植到Flatter。我们在本机应用程序中使用AES对称加密,它们与我们的设备配合良好 下面是我们试图复制java实现的颤振代码 在这里,我们向设备发送客户端(app)公钥和客户端nonce(随机16位)。设备使用设备公钥、客户端公钥和mac id创建一个加密数据包,并在加密后将其发送到应用程序。我们在应用程序上解密接收到的数据包,并在我们这边创建一个类似的数据包,然后匹配这两个数据包 在我们的例子中,它们在Flutter中都是匹配的(这表明我们
import'dart:math';
导入“dart:键入的_数据”;
导入“包:asn1lib/asn1lib.dart”;
导入“包:pc_steelcrypt/export.dart”;
进口“包装:钢穴/钢穴.省道”;
导入“package:collection/collection.dart”;
Future startEncryption()异步{
常量字符串SALT_AES_KEY='AES-KEY';
常量字符串SALT_AES_IV='AES-IV';
final Uint8List serverResponse=wait sendunecryptedCommand(getFirstMessagePayload());
最终Uint8List macId=getMacId(serverResponse);
最终Uint8List saltNonceServer=getSaltNounceServer(serverResponse);
最终Uint8List serverCertificate=getCertificate(serverResponse);
//解析服务器证书
最终ASN1Parser p=ASN1Parser(服务器证书);
最终ASN1序列signedCert=p.nextObject()作为ASN1序列;
最终ASN1序列证书=作为ASN1序列的已签名证书元素[0];
最终ASN1序列pubKeyElement=cert.elements[6]作为ASN1序列;
最终ASN1BitString pubKeyBits=pubKeyElement。元素[1]为ASN1BitString;
打印('publikeybits:$publikeybits');
//TODO:也需要对证书进行身份验证
//客户端密钥生成:
最终ECCurve_secp256r1 secp256r1=ECCurve_secp256r1();
最终ECQ点=
secp256r1.curve.decodePoint(publikeybits.contentBytes().toList());
最终ECPublicKey服务器PublicKey=ECPublicKey(Q,secp256r1);
最终ECCurve_secp256r1 _nistp256=ECCurve_secp256r1();
最终ECKeyGenerator参数ECKeyGenerator参数=
ECKeyGeneratorParameters(_nistp256);
最终SecureRandom sr=getSecureRandom();
最终参数SwithRandom参数SwithRandom=
参数Swithrandom(ECKeyGenerator参数,sr);
最终ECKeyGenerator ECKeyGenerator=ECKeyGenerator();
ecKeyGenerator.init(参数swithrandom);
final _clientKeyPair=ecKeyGenerator.generateKeyPair();
最终SecureRandom sr2=getSecureRandom();
最终Uint8List clientNonce=sr2.nextBytes(16);
final clientPubKeyRaw=getCertificateRaw(_clientKeyPair.publicKey作为ECPublicKey);
最终Uint8List消息=Uint8List(80);
copyRange(msg,0,clientPubKeyRaw,0,64);
copyRange(msg,64,clientNonce,0,16);
最终Uint8List signedData=等待发送未加密命令(msg);
final secret=serverPublicKey.Q*(_clientKeyPair.privateKey作为ECPrivateKey).d;
Uint8List sharedSecret=secret.getEncoded();
if(sharedSecret.length==33){
sharedSecret=sharedSecret.子列表(1);
}
final Uint8List aesKey=生成128位密钥forble(共享秘密、Uint8List.fromList(SALT_AES_KEY.codeUnits)、saltnoneserver、clientNonce);
final Uint8List aesIv=生成128位密钥forble(共享秘密、Uint8List.fromList(SALT_AES_IV.codeUnits)、saltnoneserver、clientNonce);
最终AesCryptRaw AesCryptRaw=AesCryptRaw(填充:PaddingAES.none,键:aesKey);
最终UINT8列表serverPubKeyRaw=getCertificateRaw(serverPubKeyRaw);
final int clientToBeSignedLength=serverPubKeyRaw.length+clientPubKeyRaw.length+macId.length;
最终Uint8List clientToBeSigned=Uint8List(clientToBeSignedLength);
copyRange(clientToBeSigned,0,serverPubKeyRaw,0,serverPubKeyRaw.length);
copyRange(clientToBeSigned,serverPubKeyRaw.length,clientPubKeyRaw,0,clientPubKeyRaw.length);
copyRange(clientToBeSigned,serverPubKeyRaw.length+clientPubKeyRaw.length,macId,0,macId.length);
最终摘要md=SHA256Digest();
md.update(clientToBeSigned,0,clientToBeSigned.length);
最终Uint8List clientHash=Uint8List(md.digestSize);
md.doFinal(clientHash,0);
最终Uint8List serverHash=aesnypter.ctr.decrypt(enc:signedData,iv:aesIv);
最终函数deepEq=deepCollectionQuality()。等于;
最终bool结果=作为bool的deepEq(serverHash,clientHash);
如果(结果){
打印(“加密成功”);
//第一次向设备发送加密命令。使用AES加密程序加密
sendEncryptedCommand(aesEncrypter,Uint8List.fromList([2,2]);
}否则{
打印(“加密失败”);
}
}
UINT8列表getCertificateRaw(ECPublicKey publicKey){
最终publicKeyRaw=UINT8列表(64);
Uint8List result=publicKey.Q.getEncoded(false);
result=result.length==65?result.sublist(1):结果;
copyRange(publicKeyRaw,0,result,0,result.length);
返回publicKeyRaw;
}
UINT8列表生成128位密钥表(UINT8列表共享密钥,
Uint8List salt、Uint8List serverNonce、Uint8List clientNonce){
最终消化器=SHA256Digest();
消化池更新(sharedSecret,0,sharedSecret.length);
蒸煮器。更新(盐,0,盐。长度);
更新(clientNonce,0,clientNonce.length);
更新(serverNonce,0,serverNonce.length);
最终Uint8List EXPUFFER=Uint8List(消化池.消化池尺寸);
蒸煮器。最终(0);
if(exputffer.length)不清楚您在哪里遇到了问题。您说有些东西匹配,但其他东西不匹配。您能否给出一个简单的示例,说明一些java代码和dart代码尝试执行相同的操作并返回不同的结果(使用测试向量)?@RichardHeap我对这个加密过程不是很确定,但据我所知,我
class EncryptionKeyPair {
private static ECParameterSpec nistp256 = new ECParameterSpec(
new EllipticCurve(
new ECFieldFp(new BigInteger
("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
16)),
new BigInteger
("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
16),
new BigInteger
("5ac635d8aa3a93e7bb2ebdb7676RE86bc651d06b45c54c0f63bce3c3e27d2604b",
16)),
new ECPoint(new BigInteger
("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A18655D898C296", 16),
new BigInteger
("3DE342FAFE2A7F9B4AA6EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
16)),
new BigInteger("FFFFFFFF00000000FFFFFFFFFFFFFFFFECE4FAAFA7179E94F4A9CAB2FC432543", 16),
1);
public ECPrivateKey mPrivate;
public ECPublicKey mPublic;
public void generateKey() throws IOException {
KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(nistp256);
KeyPair pair = kpg.generateKeyPair();
mPrivate = (ECPrivateKey) pair.getPrivate();
mPublic = (ECPublicKey) pair.getPublic();
} catch (NoSuchAlgorithmException e) {
throw new IOException("No DH keypair generator", e);
} catch (InvalidAlgorithmParameterException e) {
throw new IOException("Invalid DH parameters", e);
}
}
}
KeyAgreement ka;
try {
ka = KeyAgreement.getInstance("ECDH");
ka.init((ECPrivateKey) keyPair.mPrivate);
ka.doPhase(certificate.getPublicKey(), true);
return ka.generateSecret();
} catch (Exception e) {
e.printStackTrace();
}