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

x509 Interface #47

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open

x509 Interface #47

wants to merge 12 commits into from

Conversation

pinheadmz
Copy link
Member

@pinheadmz pinheadmz commented Apr 20, 2020

This PR is WIP for implementing a user-friendly interface for generating x509 certificates. Ideally bcrypto could be used by a Handshake application to generate an RSA private key, construct and sign an x509 certificate, and export a TLSA record for use with DANE.

So far this branch fixes a few bugs in encoding/decoding x509 and asn1, uses an internal force flag to ensure recreation of optional elements, and adds fromJSON and getJSON methods to all types.

JSON output looks like this.

The JSON output is still a bit verbose, I'm open to input on what should come next, for example a fromOptions() type system to fill in some of the boiler-plate values and simplify some of the embedded objects/arrays. And of course sign and verify methods right on the certificate.

@pinheadmz
Copy link
Member Author

Finally reached my goal of being able to generate key and ssl cert with bcrypto that can work on a Handshake website with TLSA.

Interface is pretty easy, could be more minimal with additional work, and only a few extensions and key types are currently available:

    // Create key pair and get JSON for pubkey
    const priv = rsa.privateKeyGenerate(2048);
    const pub = rsa.publicKeyCreate(priv);
    const pubJSON = rsa.publicKeyExport(pub);

    // Basic details, leave out optional and more complex stuff
    const json = {
      version: 2,
      serialNumber: 'deadbeef0101',
      signature: {
        algorithm: 'RSASHA256'
      },
      issuer: [],
      validity: {
        notBefore: { type: 'UTCTime', node: '2020-04-20T18:53:25Z' },
        notAfter: { type: 'UTCTime', node: '2021-04-20T18:53:25Z' }
      },
      subject: [],
      subjectPublicKeyInfo: {
        algorithm: {
          algorithm: 'RSAPublicKey'
        },
        publicKey: {
          modulus: pubJSON.n,
          publicExponent: pubJSON.e
        }
      },
      extensions: [
        {
          extnID: 'SubjectAltName',
          critical: false,
          extnValue: [
            { type: 'DNSName', node: '*.bcoin.io' },
            { type: 'DNSName', node: 'bcoin.io' }
          ]
        },
        {
          extnID: 'BasicConstraints',
          critical: false,
          extnValue: {cA: false, pathLenConstraint: 0}
        }
      ]
    };

    // Create to-be-signed certificate object
    const tbs = x509.TBSCertificate.fromJSON(json);

    // Use helper functions for the complicated details
    tbs.issuer = x509.Entity.fromJSON({
      COUNTRY: 'US',
      PROVINCE: 'CA',
      LOCALITY: 'San Francisco',
      ORGANIZATION: 'bcrypto',
      ORGANIZATIONALUNIT: 'encodings',
      COMMONNAME: 'bcoin.io',
      EMAILADDRESS: '[email protected]'
    });
    tbs.subject = x509.Entity.fromJSON({
      COUNTRY: 'US',
      PROVINCE: 'CA',
      LOCALITY: 'San Francisco',
      ORGANIZATION: 'bcrypto',
      ORGANIZATIONALUNIT: 'encodings',
      COMMONNAME: 'bcoin.io',
      EMAILADDRESS: '[email protected]'
    });

    // Serialize
    const msg = sha256.digest(tbs.encode());

    // Sign
    const sig = rsa.sign('SHA256', msg, priv);

    // Complete
    certFromJSON = new x509.Certificate();
    certFromJSON.tbsCertificate = tbs;
    certFromJSON.signatureAlgorithm.fromJSON({algorithm: 'RSASHA256'});
    certFromJSON.signature.fromJSON({bits: sig.length * 8, value: sig.toString('hex')});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant