npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

uasn1

v0.7.1

Published

An insanely minimal ASN.1 builder for X.509 common schemas, specifically SEC1/X9.62 PKCS#8, SPKI/PKIX, PKCS#1 and CSR.

Downloads

6,829

Readme

μASN1.js

An insanely minimal ASN.1 builder for X.509 common schemas, specifically SEC1/X9.62 PKCS#8, SPKI/PKIX, PKCS#1 and CSR.

Created for ECDSA-CSR and eckles.js (PEM-to-JWK and JWK-to-PEM).

Optimal for the times you want lightweight ASN.1 support and it's reasonable to build concise specific functions for a bounded number of supported schemas rather than a generic parser that supports all schemas.

Works exclusively in hexidecimal for simplicity and ease-of-use.

var ASN1 = require('uasn1');

API

The ASN.1 standard is actually pretty simple and fairly consistent, but it's a little tedius to construct due to how sizes are calculated with nested structures.

There are only 3 methods needed to support all of the X.509 schemas that most of us care about, and so that's all this library has:

ASN1(type, hex1, hex2, ...)
ASN1.UInt(hex1, hex2, ...)
ASN1.BitStr(hex1, hex2, ...)

/*helper*/
ASN1.numToHex(num)

Most ASN.1 types follow the same rules:

  • Type byte goes first
  • Length Info byte goes next
    • for numbers < 128 length info is read as the length
    • for numbers > 128 length info is size of the length (and the next bytes are the length)
    • 128 is a special case which essentially means "read to the end of the file"
  • The value bytes go next

The tedius part is just cascading the lengths.

Integer values are different. They must have a leading '0' if the first byte is > 127, if the number is positive (otherwise it will be considered negative).

Bit Strings are also different. The first byte is used to tell how many of the next bytes are used for alignment. For the purposes of all X509 schemas I've seen, that means it's just '0'.

As far as I've been able to tell, that's all that matters.

Examples

  • EC SEC1/X9.62
  • EC PKCS#8
  • EC SPKI/PKIX

First, some CONSTANTs:

// 1.2.840.10045.3.1.7
// prime256v1 (ANSI X9.62 named elliptic curve)
var OBJ_ID_EC_256 = '06 08 2A8648CE3D030107'.replace(/\s+/g, '').toLowerCase();

// 1.3.132.0.34
// secp384r1 (SECG (Certicom) named elliptic curve)
var OBJ_ID_EC_384 = '06 05 2B81040022'.replace(/\s+/g, '').toLowerCase();

// 1.2.840.10045.2.1
// ecPublicKey (ANSI X9.62 public key type)
var OBJ_ID_EC_PUB = '06 07 2A8648CE3D0201'.replace(/\s+/g, '').toLowerCase();

EC sec1

function packEcSec1(jwk) {
  var d = toHex(base64ToUint8(urlBase64ToBase64(jwk.d)));
  var x = toHex(base64ToUint8(urlBase64ToBase64(jwk.x)));
  var y = toHex(base64ToUint8(urlBase64ToBase64(jwk.y)));
  var objId = ('P-256' === jwk.crv) ? OBJ_ID_EC_256 : OBJ_ID_EC_384;
  return hexToUint8(
    ASN1('30'                                 // Sequence
    , ASN1.UInt('01')                         // Integer (Version 1)
    , ASN1('04', d)                           // Octet String
    , ASN1('A0', objId)                       // [0] Object ID
    , ASN1('A1', ASN1.BitStr('04' + x + y)))  // [1] Embedded EC/ASN1 public key
  );
}

EC pkcs8

function packEcPkcs8(jwk) {
  var d = toHex(base64ToUint8(urlBase64ToBase64(jwk.d)));
  var x = toHex(base64ToUint8(urlBase64ToBase64(jwk.x)));
  var y = toHex(base64ToUint8(urlBase64ToBase64(jwk.y)));
  var objId = ('P-256' === jwk.crv) ? OBJ_ID_EC_256 : OBJ_ID_EC_384;
  return hexToUint8(
    ASN1('30'
    , ASN1.UInt('00')
    , ASN1('30'
      , OBJ_ID_EC_PUB
      , objId
      )
    , ASN1('04'
      , ASN1('30'
        , ASN1.UInt('01')
        , ASN1('04', d)
        , ASN1('A1', ASN1.BitStr('04' + x + y)))))
  );
}

EC spki/pkix

function packEcSpki(jwk) {
  var x = toHex(base64ToUint8(urlBase64ToBase64(jwk.x)));
  var y = toHex(base64ToUint8(urlBase64ToBase64(jwk.y)));
  var objId = ('P-256' === jwk.crv) ? OBJ_ID_EC_256 : OBJ_ID_EC_384;
  return hexToUint8(
    ASN1('30'
    , ASN1('30'
      , OBJ_ID_EC_PUB
      , objId
      )
    , ASN1.BitStr('04' + x + y))
  );
}
var packPkix = packSpki;