我是PointyCastle的新手,如何用dart中的PointyCastle生成ecc base64密钥对
AsymmetricKeyPair<PublicKey, PrivateKey> generateKeyPair({curve = 'secp256r1'}) {
var param = curve == 'secp256r1' ? ECCurve_secp256r1() : ECCurve_secp256k1();
var keyParams = ECKeyGeneratorParameters(param);
var random = FortunaRandom();
random.seed(KeyParameter(_seed()));
var generator = ECKeyGenerator();
generator.init(ParametersWithRandom(keyParams, random));
return generator.generateKeyPair();
}
Uint8List _seed() {
var random = Random.secure();
var seed = List<int>.generate(32, (_) => random.nextInt(256));
return Uint8List.fromList(seed);
}上面我可以生成一个AsymmetricKeyPair对象,如何像我已经完成的js包那样获得公共base64和私有base64。
{"priKey":"CVK3r/UxdGCwQBjtn5vN/orUMxKf9E/1TlJzLkMz9t4=","pubKey":"BJH/mWJqgchGxXGA5/E79SsWRwVo3rpduBmD8FOs7UlKiK8PIvwrkCDvUcwhKdysW35OByPjoVcwFqg1NyumLKM="}此外,一开始,我想使用我的js包文件在颤振的android,但这将是非常困难的,我知道。
how to use js bundle in flutter android
我还需要在sha256中使用ecdsa进行符号和验证功能。
Signer signer = new Signer('SHA-256/ECDSA');
// 签名,参数:私钥,明文
ECSignature sign(String privateKeyStr, String txt) {
SecureRandom random = _setRadom();
// how to convert a plain txt to kTestBytes
final Uint8List kTestBytes = new Uint8List.fromList([1, 2, 3]);
// if I pass in base64 privateKey str, is the radix 64?
ECPrivateKey privateKey = new ECPrivateKey(BigInt.parse(privateKeyStr, radix: 10), ecDomain);
PrivateKeyParameter signParams = new PrivateKeyParameter(privateKey);
signer.init(true, new ParametersWithRandom(signParams, random));
ECSignature signature = signer.generateSignature(kTestBytes) as ECSignature;
return signature;
}
// 验签
// 参数: 明文,签名,公钥
bool verify(txt, signature, publicKey) {
// how to make the txt to kTestBytes
var kTestBytes = txt
signer.init(false, new PublicKeyParameter(publicKey));
bool verify = signer.verifySignature(kTestBytes, signature);
// print(verify);
return verify;
}
// I don't know what this function actually do,as I know in other language ecdsa don;t need a random number.
SecureRandom _setRadom() {
List<int> key = [67, 3, 241, 75, 143, 78, 115, 99, 21, 242, 180, 43, 26, 7, 194, 20];
List<int> iv = [87, 117, 137, 182, 2, 199, 132, 230, 120, 12, 109, 177, 34, 197, 186, 206];
KeyParameter keyParam = new KeyParameter(new Uint8List.fromList(key));
ParametersWithIV<KeyParameter> paramsIV = new ParametersWithIV(keyParam, new Uint8List.fromList(iv));
SecureRandom random = new SecureRandom('AES/CTR/AUTO-SEED-PRNG')..seed(paramsIV);
return random;
}在任何地方我都可以找到示例代码,这些功能在互联网上被一些副本改变了。我在评论中有很多困惑的列表
发布于 2022-06-16 13:28:55
EC密钥将作为Base64编码的原始私钥和Base64编码的原始未压缩公钥导出/导入。
首先,可以说,在生成新的密钥对时,使用已发布的代码进行签名和验证是有效的:
AsymmetricKeyPair<PublicKey, PrivateKey> kp = generateKeyPair();
ECSignature signature = sign(kp.privateKey as ECPrivateKey, "The quick brown fox jumps over the lazy dog");
bool verified = verify("The quick brown fox jumps over the lazy dog", signature, kp.publicKey as ECPublicKey);
print(verified); // true例如,在下面的文章中,我将重点讨论密钥的导入/导出。原始密钥封装在ECPrivateKey和ECPublicKey中,可以按以下方式导出和导入:
String p256 = 'secp256r1';
AsymmetricKeyPair<PublicKey, PrivateKey> kp = generateKeyPair(curve: p256);
// Export
BigInt d = (kp.privateKey as ECPrivateKey).d!;
BigInt x = (kp.publicKey as ECPublicKey).Q!.x!.toBigInteger()!;
BigInt y = (kp.publicKey as ECPublicKey).Q!.y!.toBigInteger()!;
// Import
ECDomainParameters domain = ECDomainParameters(p256);
ECPrivateKey ecPrivateKey = ECPrivateKey(d, domain);
ECPublicKey ecPublicKey = ECPublicKey(domain.curve.createPoint(x, y), domain);这里,d是原始私钥,x和y是原始公钥的x和y坐标。
在JavaScript方面,使用Base64编码的原始私钥,使用Base64编码的原始未压缩密钥,其中未压缩密钥是级联0x04 + <x> + <y>。因此,对于出口和进口,适用以下规定:
关于导出,
d、x和y派生出Base64编码的原始私钥和公钥,如下所示:字符串rawPrivateB64 = exportPrivate(d);字符串rawUncompressedPublicB64 = exportPublic(x,y,32);
使用
导入‘dart:转换’;导入‘包:nanodart/nanodart.dart’;字符串exportPrivate(BigInt d){返回base64Encode(NanoHelpers.bigIntToBytes(d));} String exportPublic(BigInt,BigInt y,int size){返回exportPublic(NanoHelpers.bigIntToBytes( x ),大小),pad(NanoHelpers.bigIntToBytes(y),size) );} Uint8List pad(Uint8List list,int size){ Uint8List pad= list;int currSize = list.length;如果(currSize < size){ Uint8List pad = Uint8List(size - currSize);pad= NanoHelpers.concat(pad,list);}返回衬垫;}
在exportPublic()中作为第三个参数传递的大小是生成点的顺序大小(secp256r1为32个字节)。如果x或y较小,则从前面填充0x00值,直到达到所需长度为止。
对于从BigInt到Uint8List的转换和连接,为了简单起见,我使用了NanoDart包中的NanoHelpers类。当然,这里也可以使用其他实现。
d、x和y可以从Base64编码的原始私钥和公钥派生,如下所示:BigInt d= importPrivate(rawPrivateB64);List xy = importPublic(rawUncompressedPublicB64);BigInt x= xy.elementAt(0);BigInt y= xy.elementAt(1);
使用
BigInt importPrivate(String d){返回NanoHelpers.byteToBigInt(base64Decode(d));} List importPublic(String xy){ Uint8List xyBytes = base64Decode(xy);xyBytes = xyBytes.sublist(1,xyBytes.length);int size = xyBytes.length ~/ 2;Uint8List x= xyBytes.sublist(0,size);Uint8List y= xyBytes.sublist(size);int NanoHelpers.byteToBigInt(x),NanoHelpers.byteToBigInt(y);}en19#
测试
已发布的密钥对
{"priKey":"CVK3r/UxdGCwQBjtn5vN/orUMxKf9E/1TlJzLkMz9t4=","pubKey":"BJH/mWJqgchGxXGA5/E79SsWRwVo3rpduBmD8FOs7UlKiK8PIvwrkCDvUcwhKdysW35OByPjoVcwFqg1NyumLKM="}可以导入并用于签署和验证,如下所示:
String rawPrivateB64 = "CVK3r/UxdGCwQBjtn5vN/orUMxKf9E/1TlJzLkMz9t4=";
String rawUncompressedPublicB64 = "BJH/mWJqgchGxXGA5/E79SsWRwVo3rpduBmD8FOs7UlKiK8PIvwrkCDvUcwhKdysW35OByPjoVcwFqg1NyumLKM=";
BigInt d = importPrivate(rawPrivateB64);
List xy = importPublic(rawUncompressedPublicB64);
BigInt x = xy.elementAt(0);
BigInt y = xy.elementAt(1);
ECDomainParameters domain = ECDomainParameters('secp256r1');
ECPrivateKey private = ECPrivateKey(d, domain);
ECPublicKey public = ECPublicKey(domain.curve.createPoint(x, y), domain);
ECSignature signature = sign(private, "The quick brown fox jumps over the lazy dog");
bool verified = verify("The quick brown fox jumps over the lazy dog", signature, public);
print(verified); // true编辑:关于您的评论:sign()和verify()是您发布的方法,但是根据更改,现在直接传递键(而不是字符串),并使用utf8.encode()为UTF-8编码应用实际消息(而不是[1,2,3]):
import 'dart:convert';
ECSignature sign(ECPrivateKey privateKey, String txt) {
SecureRandom random = _setRandom();
Uint8List txtBytes = Uint8List.fromList(utf8.encode(txt));
PrivateKeyParameter signParams = PrivateKeyParameter(privateKey);
signer.init(true, ParametersWithRandom(signParams, random));
ECSignature signature = signer.generateSignature(txtBytes) as ECSignature;
return signature;
}
bool verify(String txt, ECSignature signature, ECPublicKey publicKey) {
signer.init(false, PublicKeyParameter(publicKey));
bool verify = signer.verifySignature(Uint8List.fromList(utf8.encode(txt)), signature);
return verify;
}作为_setRandom(),我应用了来自generateKeyPair()的实现,而不是您的实现(即基于FortunaRandom()的CSPRNG)。
发布于 2022-06-20 07:25:52
我的全部代码都是基于公认的答案
crypto.dart
import "dart:typed_data";
import "dart:math";
import 'dart:convert';
import "package:pointycastle/export.dart";
import './utils.dart';
Signer signer = new Signer('SHA-256/ECDSA');
class Crypto {
final ECDomainParameters ecDomain = new ECDomainParameters('secp256r1');
/// 公私钥对生成
/// 关于公私钥encoding:https://stackoverflow.com/questions/72641616/how-to-convert-asymmetrickeypair-to-base64-encoding-string-in-dart
///
Map generateKeyPair({curve = 'secp256r1'}) {
var param = curve == 'secp256r1' ? ECCurve_secp256r1() : ECCurve_secp256k1();
var keyParams = ECKeyGeneratorParameters(param);
var random = FortunaRandom();
random.seed(KeyParameter(this._seed(32)));
var generator = ECKeyGenerator();
generator.init(ParametersWithRandom(keyParams, random));
AsymmetricKeyPair<PublicKey, PrivateKey> kp = generator.generateKeyPair();
BigInt d = (kp.privateKey as ECPrivateKey).d!;
BigInt x = (kp.publicKey as ECPublicKey).Q!.x!.toBigInteger()!;
BigInt y = (kp.publicKey as ECPublicKey).Q!.y!.toBigInteger()!;
String rawPrivateB64 = exportPrivate(d);
String rawUncompressedPublicB64 = exportPublic(x, y, 32);
return {'base64Pub': rawUncompressedPublicB64, 'base64Priv': rawPrivateB64};
}
Uint8List _seed(size) {
var random = Random.secure();
var seed = List<int>.generate(size, (_) => random.nextInt(256));
return Uint8List.fromList(seed);
}
// TODO
// Restore the ECPrivateKey from 'd'.
restoreKeyFromPrivate(privateKeyStr) {
ECPrivateKey privateKey = new ECPrivateKey(BigInt.parse(privateKeyStr, radix: 10), ecDomain);
ECPoint Q = privateKey.parameters!.G * privateKey.d as ECPoint;
ECPublicKey publicKey = new ECPublicKey(Q, privateKey.parameters);
return publicKey;
}
ECSignature sign(ECPrivateKey privateKey, String txt) {
SecureRandom random = _setRandom();
Uint8List txtBytes = Uint8List.fromList(utf8.encode(txt));
PrivateKeyParameter signParams = PrivateKeyParameter(privateKey);
signer.init(true, ParametersWithRandom(signParams, random));
ECSignature signature = signer.generateSignature(txtBytes) as ECSignature;
return signature;
}
bool verify(String txt, ECSignature signature, ECPublicKey publicKey) {
signer.init(false, PublicKeyParameter(publicKey));
bool verify = signer.verifySignature(Uint8List.fromList(utf8.encode(txt)), signature);
return verify;
}
SecureRandom _setRandom() {
// List<int> key = [67, 3, 241, 75, 143, 78, 115, 99, 21, 242, 180, 43, 26, 7, 194, 20];
// List<int> iv = [87, 117, 137, 182, 2, 199, 132, 230, 120, 12, 109, 177, 34, 197, 186, 206];
List<int> key = _seed(16);
List<int> iv = _seed(16);
KeyParameter keyParam = new KeyParameter(new Uint8List.fromList(key));
ParametersWithIV<KeyParameter> paramsIV = new ParametersWithIV(keyParam, new Uint8List.fromList(iv));
SecureRandom random = new SecureRandom('AES/CTR/AUTO-SEED-PRNG')..seed(paramsIV);
return random;
}
}crypto_test.dart
import '../lib/crypto/crypto.dart';
import "dart:typed_data";
import "dart:math";
import '../lib/crypto/utils.dart';
import "package:pointycastle/export.dart";
var crypto = new Crypto();
void main() {
// _generateTest();
// _signTest();
Map keyPair = crypto.generateKeyPair();
String rawPrivateB64 = keyPair['base64Priv'];
String rawUncompressedPublicB64 = keyPair['base64Pub'];
BigInt d = importPrivate(rawPrivateB64);
List xy = importPublic(rawUncompressedPublicB64);
BigInt x = xy.elementAt(0);
BigInt y = xy.elementAt(1);
ECDomainParameters domain = ECDomainParameters('secp256r1');
ECPrivateKey private = ECPrivateKey(d, domain);
ECPublicKey public = ECPublicKey(domain.curve.createPoint(x, y), domain);
ECSignature signature = crypto.sign(private, "The quick brown fox jumps over the lazy dog");
bool verified = crypto.verify("The quick brown fox jumps over the lazy dog", signature, public);
print('验签结果');
print(verified); // true
}
_generateTest() {
Map keyPair = crypto.generateKeyPair();
print("结果");
print(keyPair['base64Pub']);
print(keyPair['base64Priv']);
}
_signTest() {
// AsymmetricKeyPair<PublicKey, PrivateKey> kp = crypto.generateKeyPair();
// ECSignature signature = sign(kp.privateKey as ECPrivateKey, "The quick brown fox jumps over the lazy dog");
// bool verified = crypto.verify("The quick brown fox jumps over the lazy dog", signature, kp.publicKey as ECPublicKey);
// print(verified); // true
}https://stackoverflow.com/questions/72641616
复制相似问题