在 Dart 中将 ECPrivateKey/ECPublicKey 转换为 PEM 字符串
Posted
技术标签:
【中文标题】在 Dart 中将 ECPrivateKey/ECPublicKey 转换为 PEM 字符串【英文标题】:Convert ECPrivateKey/ECPublicKey to PEM string in Dart 【发布时间】:2019-09-27 11:01:50 【问题描述】:我有一个 ECPrivateKey/ECPublicKey,想将其转换为如下 PEM 字符串
公钥:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnd21ku0m+VZvM3tJAP3IIM3XXGla
PM2zhRura+/qioJoUwDK7qLbuFzcmbHHx6ELnXFXgAjDbZgFyMdfcm1ugw==
-----END PUBLIC KEY-----
私钥:
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg2sfmpsl894GDcNOl
vzKW0gzf/b8XvQigr/rZGSjKydqhRANCAASd3bWS7Sb5Vm8ze0kA/cggzddcaVo8
zbOFG6tr7+qKgmhTAMruotu4XNyZscfHoQudcVeACMNtmAXIx19ybW6D
-----END PRIVATE KEY-----
【问题讨论】:
您可以展示您尝试过的内容或您正在使用的加密库。预计您会进行一些初步研究,但目前没有显示。 【参考方案1】:如果你喂
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnd21ku0m+VZvM3tJAP3IIM3XXGla PM2zhRura+/qioJoUwDK7qLbuFzcmbHHx6ELnXFXgAjDbZgFyMdfcm1ugw==
进入像this 这样的ASN.1 解析器,您会发现它只是一些oid(包括曲线)和密钥的R/S 值的Base64/ASN.1 编码。该编码在 PKCS#8 规范中有所描述。
SEQUENCE (2 elem) SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type)
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)
BIT STRING (520 bit) 0000010010011101110111011011010110010010111011010010011011111001010101…
使用Dart ASN encoder/decoder package 首先解码上面的示例,以探索 ASN 组件的顺序和嵌套。然后反转该过程并使用库的编码器部分对其进行重新编码,并断言您将获得与开始时相同的 BER 编码。现在您可以对任何您喜欢的密钥进行编码。
【讨论】:
ECDSA signature 有 R & S 组件(最多 n 个); EC publickey 包含 if 未压缩的点(如这里)具有前缀 04 然后仿射 X 和 Y 坐标(对于素数曲线最多 p);请参阅 rfc5480 sec 2.2 和 X9.62 或(更便宜的)SEC1。对于 PKCS8 格式的私钥,请参阅 rfc5280 sec 4 和 rfc5915 或 SEC1。【参考方案2】:查看 Dart Basic Utils 包。我通过使用 Pointycastle 和 ASN1 包完成了这项工作。
更新 pubspec.yaml 并将以下行添加到您的依赖项中。
dependencies:
basic_utils: ^2.5.6
存储库:https://github.com/Ephenodrom/Dart-Basic-Utils
Pub.dev:https://pub.dev/packages/basic_utils
String encodeEcPublicKeyToPem(ECPublicKey publicKey);
String encodeEcPrivateKeyToPem(ECPrivateKey ecPrivateKey);
如果你不想使用包,这里是完整的代码:
static String encodeEcPublicKeyToPem(ECPublicKey publicKey)
ASN1ObjectIdentifier.registerFrequentNames();
var outer = ASN1Sequence();
var algorithm = ASN1Sequence();
algorithm.add(ASN1ObjectIdentifier.fromName('ecPublicKey'));
algorithm.add(ASN1ObjectIdentifier.fromName('prime256v1'));
var subjectPublicKey = ASN1BitString(publicKey.Q.getEncoded(false));
outer.add(algorithm);
outer.add(subjectPublicKey);
var dataBase64 = base64.encode(outer.encodedBytes);
var chunks = StringUtils.chunk(dataBase64, 64);
return '$BEGIN_EC_PUBLIC_KEY\n$chunks.join('\n')\n$END_EC_PUBLIC_KEY';
static String encodeEcPrivateKeyToPem(ECPrivateKey ecPrivateKey)
ASN1ObjectIdentifier.registerFrequentNames();
var outer = ASN1Sequence();
var version = ASN1Integer(BigInt.from(1));
var privateKeyAsBytes = _bigIntToBytes(ecPrivateKey.d);
var privateKey = ASN1OctetString(privateKeyAsBytes);
var choice = ASN1Sequence(tag: 0xA0);
choice
.add(ASN1ObjectIdentifier.fromName(ecPrivateKey.parameters.domainName));
var publicKey = ASN1Sequence(tag: 0xA1);
var subjectPublicKey =
ASN1BitString(ecPrivateKey.parameters.G.getEncoded(false));
publicKey.add(subjectPublicKey);
outer.add(version);
outer.add(privateKey);
outer.add(choice);
outer.add(publicKey);
var dataBase64 = base64.encode(outer.encodedBytes);
var chunks = StringUtils.chunk(dataBase64, 64);
return '$BEGIN_EC_PRIVATE_KEY\n$chunks.join('\n')\n$END_EC_PRIVATE_KEY';
【讨论】:
这在 base64.encode(outer.encodedBytes);在 publicKey 中,它说它是 null以上是关于在 Dart 中将 ECPrivateKey/ECPublicKey 转换为 PEM 字符串的主要内容,如果未能解决你的问题,请参考以下文章