ASN.1 Parser Utility
parse-asn1 is a utility library designed for parsing Abstract Syntax Notation One (ASN.1) encoded data. It is primarily used within the `crypto-browserify` ecosystem, serving as a dependency for libraries like `browserify-sign` to handle cryptographic artifacts such as X.509 certificates and private keys. The current stable version is 5.1.9, with the last update approximately 7 months ago, indicating a maintenance-focused release cadence. The library provides a JavaScript implementation for interpreting BER/DER encoded binary data into a structured JavaScript object. A key differentiator is its role in providing browser compatibility for Node.js's crypto functionalities, though ASN.1 parsing itself is inherently complex and a common source of security vulnerabilities if not handled robustly.
Common errors
-
Error: Expected constructed type but found primitive
cause The ASN.1 parser encountered a primitive encoding where a constructed type (like a SEQUENCE or SET) was expected, or vice-versa. This often indicates malformed ASN.1 data or an incorrect expectation about the input structure.fixVerify the integrity and correctness of your ASN.1 input data. If the data is from an external source, ensure it adheres to the expected encoding rules (e.g., DER vs. BER). Debug by examining the raw bytes around the reported error position to understand the ASN.1 tag and length values. -
TypeError: Cannot read properties of undefined (reading 'value')
cause This typically occurs when trying to access properties of the object returned by `parseASN1` without proper error checking, and the parsing failed or returned an unexpected (e.g., `null` or `undefined`) result.fixAlways wrap calls to `parseASN1` in a `try...catch` block and check if the returned value is valid before attempting to access its properties. The `parseASN1` function may throw an error directly for invalid input. -
Error: Unsupported tag or invalid length
cause The parser encountered an ASN.1 tag that it does not recognize or a length field that is malformed or inconsistent with the remaining data.fixInspect the raw ASN.1 binary data at the reported offset. Confirm that the tag and length bytes are correctly formed according to ASN.1 BER/DER specifications. This might indicate corrupted data or an unsupported ASN.1 structure.
Warnings
- breaking Version 5.1.7 downgraded its internal dependency `asn1.js` from v5 to v4 due to `asn1.js` v5 dropping support for Node.js versions older than 4. Users on very old Node.js runtimes (pre-v4) might encounter issues or require specific dependency pinning if they relied on newer `asn1.js` features through `parse-asn1`.
- breaking Major version changes (v3.0.0, v4.0.0, v5.0.0) in 'parse-asn1' often correspond to significant updates or changes in its underlying dependencies, particularly `asn1.js` or `browserify-aes`. While specific breaking API changes aren't always explicitly detailed in simple changelog entries, these major bumps indicate potential shifts in behavior or required input/output formats, especially concerning how different cryptographic key types (e.g., 'PRIVATE KEY' vs 'EC PRIVATE KEY') are handled.
- gotcha ASN.1 parsing, especially in security-critical contexts like X.509 certificates, is notoriously complex and prone to implementation errors (e.g., handling indefinite lengths, tag class mismatches, malleable encodings). Incorrect parsing can lead to vulnerabilities such as signature bypasses or misinterpretation of data.
- gotcha The library expects binary input as a Node.js `Buffer` or `Uint8Array`. Passing other types, such as plain strings (unless they are a direct representation like hex strings that you explicitly convert), will result in parsing errors.
Install
-
npm install parse-asn1 -
yarn add parse-asn1 -
pnpm add parse-asn1
Imports
- parseASN1
import { parseASN1 } from 'parse-asn1'; // Incorrect for default export const { parseASN1 } = require('parse-asn1'); // Incorrect for default exportimport parseASN1 from 'parse-asn1'; // Or for CommonJS: const parseASN1 = require('parse-asn1');
Quickstart
import parseASN1 from 'parse-asn1';
import { Buffer } from 'buffer';
// Example: A simple DER-encoded ASN.1 sequence
// This represents a SEQUENCE containing an INTEGER (value 1) and a BOOLEAN (value true)
// 30 07 -- Sequence, length 7
// 02 01 01 -- Integer, length 1, value 1
// 01 01 ff -- Boolean, length 1, value true
const asn1DerBuffer = Buffer.from([
0x30, 0x07,
0x02, 0x01, 0x01,
0x01, 0x01, 0xFF
]);
try {
const parsed = parseASN1(asn1DerBuffer);
console.log('Successfully parsed ASN.1 data:');
console.log(JSON.stringify(parsed, null, 2));
// Accessing elements (example output structure might vary slightly)
if (parsed && Array.isArray(parsed.value)) {
const integerNode = parsed.value[0];
const booleanNode = parsed.value[1];
console.log(`First element (Integer): Type ${integerNode.type}, Value ${integerNode.value.toString('hex')}`);
console.log(`Second element (Boolean): Type ${booleanNode.type}, Value ${booleanNode.value.toString('hex')}`);
}
} catch (error) {
console.error('Error parsing ASN.1 data:', error.message);
}
// Another example: a simple OID
// 06 03 2A 86 48 (1.2.840)
const oidBuffer = Buffer.from([0x06, 0x03, 0x2A, 0x86, 0x48]);
try {
const parsedOid = parseASN1(oidBuffer);
console.log('\nSuccessfully parsed OID:');
console.log(JSON.stringify(parsedOid, null, 2));
} catch (error) {
console.error('Error parsing OID:', error.message);
}