0

I have a ECPrivateKey/ECPublicKey, want to convert it to PEM string like below

PublicKey:

-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnd21ku0m+VZvM3tJAP3IIM3XXGla PM2zhRura+/qioJoUwDK7qLbuFzcmbHHx6ELnXFXgAjDbZgFyMdfcm1ugw== -----END PUBLIC KEY-----

PrivateKey:

-----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg2sfmpsl894GDcNOl vzKW0gzf/b8XvQigr/rZGSjKydqhRANCAASd3bWS7Sb5Vm8ze0kA/cggzddcaVo8 zbOFG6tr7+qKgmhTAMruotu4XNyZscfHoQudcVeACMNtmAXIx19ybW6D -----END PRIVATE KEY-----

Diwa Har
  • 49
  • 7
  • You may show what you've tried or what crypto lib your are using. Some initial research is expected of you, and currently none is showing. – Maarten Bodewes Sep 27 '19 at 17:48

2 Answers2

1

If you feed

MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnd21ku0m+VZvM3tJAP3IIM3XXGla PM2zhRura+/qioJoUwDK7qLbuFzcmbHHx6ELnXFXgAjDbZgFyMdfcm1ugw==

into an ASN.1 parser like this, you find that it is simply a Base64/ASN.1 encoding of a few oids (including the curve) and the R/S values of the key. That encoding is described in the PKCS#8 spec.

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…

Use the Dart ASN encoder/decoder package to first decode that example above to explore the order and nesting of the ASN components. Then reverse the process and re-encode them using the encoder part of the library and assert that you get back the same BER encoding that you started with. Now you can encode any key you like.

Richard Heap
  • 48,344
  • 9
  • 130
  • 112
  • ECDSA _signature_ has R & S components (up to n); EC publickey contains point that _if_ uncompressed (as here) has prefix 04 then affine **X & Y coordinates** (up to p for a prime curve); see rfc5480 sec 2.2 and X9.62 or (cheaper) SEC1. For privatekey in PKCS8 format, see rfc5280 sec 4 and rfc5915 or SEC1. – dave_thompson_085 Sep 27 '19 at 23:06
0

Check out the Dart Basic Utils package. I have done this by using Pointycastle and the ASN1 package.

Update pubspec.yaml and add the following line to your dependencies.

dependencies:
  basic_utils: ^2.5.6

Repository : https://github.com/Ephenodrom/Dart-Basic-Utils

Pub.dev : https://pub.dev/packages/basic_utils

String encodeEcPublicKeyToPem(ECPublicKey publicKey);
String encodeEcPrivateKeyToPem(ECPrivateKey ecPrivateKey);

Here is the full code if you don't want to use a package:

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';
  }
Ephenodrom
  • 1,797
  • 2
  • 16
  • 28