Generic ASN.1 parser/decoder that can decode any valid ASN.1 DER or BER structures.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Comprehensive support for hexadecimal and Base64 input formats, including PEM armoring and various encoding standards.
Decode hexadecimal strings and arrays into binary data with flexible whitespace handling.
class Hex {
/**
* Decode hexadecimal string or array into binary data
* @param a - Hexadecimal string or array of character codes representing hex data
* @returns Uint8Array (when available) or regular array of bytes
* @throws Error if hex encoding is invalid or incomplete
*/
static decode(a: string | ArrayLike<number>): Uint8Array | number[];
}Usage Examples:
import { Hex } from '@lapo/asn1js/hex.js';
// Basic hex decoding
const hexString = "48656C6C6F20576F726C64";
const bytes = Hex.decode(hexString);
console.log(bytes); // [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
// Lowercase hex
const lowerHex = "deadbeef";
const decoded = Hex.decode(lowerHex);
console.log(decoded); // [222, 173, 190, 239]
// Hex with whitespace (automatically ignored)
const spacedHex = "30 0C 06 03 2B 65 70 05 00";
const result = Hex.decode(spacedHex);
console.log(result); // [48, 12, 6, 3, 43, 101, 112, 5, 0]
// Hex with various whitespace characters (tabs, newlines, etc.)
const formattedHex = `30 0C 06 03
\t2B 65 70 05
\u00A000`;
const cleanResult = Hex.decode(formattedHex);
// From array of character codes
const charCodes = [52, 56, 54, 53, 54, 67]; // "48656C"
const fromArray = Hex.decode(charCodes);
console.log(fromArray); // [72, 101, 108]Comprehensive Base64 decoding with support for standard Base64, Base64url, and PEM armoring.
class Base64 {
/**
* Decode base64 string or array into binary data
* Supports both standard Base64 and Base64url (RFC 4648)
* @param a - Base64 string or array of character codes
* @returns Uint8Array (when available) or regular array of bytes
* @throws Error if base64 encoding is invalid
*/
static decode(a: string | ArrayLike<number>): Uint8Array | number[];
/**
* Format base64 string with proper padding and line breaks
* Converts Base64url to standard Base64 and adds proper formatting
* @param str - Base64 string to format
* @returns Formatted base64 string with padding and 80-column line breaks
*/
static pretty(str: string): string;
/**
* Extract and decode base64 from PEM or other armored formats
* Automatically detects and handles:
* - PEM format (-----BEGIN...-----END-----)
* - begin-base64...==== format
* - Raw base64 strings
* @param a - Armored or raw base64 string
* @returns Decoded binary data
* @throws Error if no valid base64 content found
*/
static unarmor(a: string): Uint8Array | number[];
/** Regular expression for detecting armored base64 content */
static re: RegExp;
}Usage Examples:
import { Base64 } from '@lapo/asn1js/base64.js';
// Basic base64 decoding
const base64String = "SGVsbG8gV29ybGQ=";
const bytes = Base64.decode(base64String);
console.log(bytes); // [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
// Base64url decoding (automatically handled)
const base64url = "SGVsbG8gV29ybGQ"; // No padding
const urlDecoded = Base64.decode(base64url);
// Decode with whitespace (automatically ignored)
const spacedBase64 = `SGVs
bG8g
V29y
bGQ=`;
const spacedResult = Base64.decode(spacedBase64);
// PEM format decoding
const pemCert = `-----BEGIN CERTIFICATE-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxomBdI7QQ9PbTFKnRkTG
6LMU1Z4YuYcU5xDiIwz8sIBH2Z3f3X3bR0lPb0ZsU4U6z7z8z8z8z8z8z8z8z8z8
-----END CERTIFICATE-----`;
const certData = Base64.unarmor(pemCert);
// begin-base64 format
const beginBase64 = `begin-base64 644 certificate.der
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxomBdI7QQ9PbTFKnRkTG
====`;
const beginData = Base64.unarmor(beginBase64);
// Raw base64 (also works with unarmor)
const rawBase64 = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A";
const rawData = Base64.unarmor(rawBase64);
// Format base64 for display
const longBase64 = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxomBdI7QQ9PbTFKnRkTG6LMU1Z4YuYcU5xDiIwz8sIBH2Z3f3X3bR0lPb0ZsU4U6z7z8z8z8z8z8z8z8z8z8";
const formatted = Base64.pretty(longBase64);
console.log(formatted);
// Output: 80-character lines with proper padding
// Check what format a string uses
if (Base64.re.test(pemCert)) {
console.log("Contains armored base64");
}Examples showing how to use format support with ASN.1 parsing.
import { ASN1 } from '@lapo/asn1js';
import { Hex } from '@lapo/asn1js/hex.js';
import { Base64 } from '@lapo/asn1js/base64.js';
// Parse from various input formats
function parseASN1FromAnyFormat(input) {
let binaryData;
// Try to determine format and decode accordingly
if (typeof input === 'string') {
if (/^[0-9A-Fa-f\s]+$/.test(input)) {
// Looks like hex
binaryData = Hex.decode(input);
} else if (Base64.re.test(input) || /^[A-Za-z0-9+/=\s]+$/.test(input)) {
// Looks like base64 or PEM
binaryData = Base64.unarmor(input);
} else {
throw new Error('Unknown input format');
}
} else {
// Assume binary array
binaryData = input;
}
return ASN1.decode(binaryData);
}
// Examples of different input formats
const hexInput = "30 0C 06 03 2B 65 70 05 00";
const base64Input = "MAwGAytlcAUA";
const pemInput = `-----BEGIN PUBLIC KEY-----
MAwGAytlcAUA
-----END PUBLIC KEY-----`;
// All parse to the same ASN.1 structure
const fromHex = parseASN1FromAnyFormat(hexInput);
const fromBase64 = parseASN1FromAnyFormat(base64Input);
const fromPem = parseASN1FromAnyFormat(pemInput);
console.log(fromHex.toPrettyString());
console.log(fromBase64.toPrettyString());
console.log(fromPem.toPrettyString());
// Convert between formats
const asn1 = ASN1.decode(Hex.decode("300C06032B6570050000"));
const asHex = asn1.toHexString();
const asBase64 = asn1.toB64String();
const asBase64Std = asn1.toB64String('std');
console.log("Hex:", asHex);
console.log("Base64url:", asBase64);
console.log("Base64 standard:", asBase64Std);
// Create PEM-like output
const pemLike = `-----BEGIN ASN1 STRUCTURE-----
${Base64.pretty(asBase64Std)}
-----END ASN1 STRUCTURE-----`;
console.log(pemLike);The format support classes provide detailed error information for invalid input.
import { Hex } from '@lapo/asn1js/hex.js';
import { Base64 } from '@lapo/asn1js/base64.js';
// Hex error examples
try {
Hex.decode("48656C6C6F2"); // Incomplete hex (odd number of characters)
} catch (e) {
console.log(e.message); // "Hex encoding incomplete: 4 bits missing"
}
try {
Hex.decode("48656C6G"); // Invalid hex character 'G'
} catch (e) {
console.log(e.message); // "Illegal character at offset 6"
}
// Base64 error examples
try {
Base64.decode("SGVsbG8g!"); // Invalid base64 character '!'
} catch (e) {
console.log(e.message); // "Illegal character at offset 8"
}
try {
Base64.decode("SGVsbG8"); // Incomplete base64
} catch (e) {
console.log(e.message); // "Base64 encoding incomplete: at least 2 bits missing"
}
// PEM error examples
try {
Base64.unarmor("-----BEGIN CERTIFICATE-----\nInvalid content\n-----END CERTIFICATE-----");
} catch (e) {
console.log(e.message); // Base64 decoding error
}