在 Dart 中将 ECPrivateKey/ECPublicKey 转换为 PEM 字符串



我有一个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-----

如果你喂食

MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnd21ku0m+VZvM3tJAP3IIM3XXGla PM2zhRura+/qioJoUwDK7qLbuFzcmbHHx6ELnXFXgAjDbZgFyMdfcm1ugw==

进入像这样的 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 编码器/解码器包首先解码上面的示例,以探索 ASN 组件的顺序和嵌套。然后反转该过程并使用库的编码器部分重新编码它们,并断言您返回与开始时相同的 BER 编码。现在,您可以对任何您喜欢的键进行编码。

查看 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_KEYn${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_KEYn${chunks.join('n')}n$END_EC_PRIVATE_KEY';
}

最新更新