Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating PKCS8 PrivateKeyInfo seems to be missing 0x04 0x20 #82

Open
CMCDragonkai opened this issue Oct 6, 2022 · 1 comment
Open
Labels
help wanted Extra attention is needed

Comments

@CMCDragonkai
Copy link

CMCDragonkai commented Oct 6, 2022

I'm trying to use asn1-pkcs8 to construct a PrivateKeyInfo for Ed25519 private key.

I noticed that during construction the serialized buffer looks different from the one that is produced by @peculiar/webcrypto. It turns out that it's missing 0x04 0x20 prefix on the key.

import * as asn1 from '@peculiar/asn1-schema';
import * as asn1Pkcs8 from '@peculiar/asn1-pkcs8';
import * as asn1X509 from '@peculiar/asn1-x509';
import * as x509 from '@peculiar/x509';

  const algorithm = new asn1X509.AlgorithmIdentifier({
    algorithm: x509.idEd25519
  });

  // Notice I had to put `0x04 0x20` here manually
  const key = new asn1Pkcs8.PrivateKey(
    Buffer.concat([
      Buffer.from([0x04, 0x20]),
      privateKey
    ])
  );

  const pkcs8 = new asn1Pkcs8.PrivateKeyInfo({
    privateKeyAlgorithm: algorithm,
    privateKey: key,
  });

  // This should be 48 bytes, if I don't add `0x04 0x20` above, it ends up being 46 bytes
  const data = utils.bufferWrap(asn1.AsnSerializer.serialize(pkcs8));

If I don't concatenate 0x04 0x20, the resulting key size is 46 bytes.

But if I use webcrypto, I get 48 bytes.

The interface for PrivateKeyInfo requires PrivateKey which extends OctetString.

I'm trying to reconcile the difference here, it seems webcrypto is more correct here. So I'm wondering if something was missing about how PrivateKeyInfo should be constructed.

I noticed that PrivateKeyInfo in webcrypto-core is not the same as the one in asn1-pkcs8.

@microshine
Copy link
Contributor

I've updated your example. You should convert your privateKey variable into the OctetString class from @peculiar/asn1-schema package.

PrivateKeyInfo.PrivateKey keeps private key data. It's OCTET STRING for ED25519, but SEQUENCE for RSA. So you should create and serialize the correct data for the PrivateKey field

const crypto = require('crypto').webcrypto
const asn1 = require('@peculiar/asn1-schema');
const asn1Pkcs8 = require('@peculiar/asn1-pkcs8');
const asn1X509 = require('@peculiar/asn1-x509');

const algorithm = new asn1X509.AlgorithmIdentifier({
  algorithm: '1.3.101.112',
});

// ED private key data
const raw = crypto.getRandomValues(new Uint8Array(32))

// CurvePrivateKey ::= OCTET STRING
const curvePrivateKey = new asn1.OctetString(raw.byteLength);
// copy raw
const edPrivateKeyVew = new Uint8Array(curvePrivateKey.buffer);
edPrivateKeyVew.set(raw);

const pkcs8 = new asn1Pkcs8.PrivateKeyInfo({
  privateKeyAlgorithm: algorithm,
  privateKey: new asn1Pkcs8.PrivateKey(asn1.AsnConvert.serialize(curvePrivateKey)),
});

console.log(asn1.AsnConvert.toString(pkcs8));
console.log();
console.log("HEX:", Buffer.from(asn1.AsnConvert.serialize(pkcs8)).toString("hex"));

Console

SEQUENCE :
  INTEGER : 0
  SEQUENCE :
    OBJECT IDENTIFIER : 1.3.101.112
  OCTET STRING :
    OCTET STRING : 5d50746f08d85888ab2ec91d0bd14b92a96e24e5d90f7d7265a33ac9c1d08413

HEX: 302e020100300506032b6570042204205d50746f08d85888ab2ec91d0bd14b92a96e24e5d90f7d7265a33ac9c1d08413

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants