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
Efficient byte-level stream processing with zero-copy approach for optimal performance when parsing ASN.1 data.
The Stream class manages byte-level access to data with a zero-copy approach, supporting both binary arrays and strings.
/**
* Stream for efficient byte-level processing
* @param enc - Source data (Stream, array, or string) - data will not be copied
* @param pos - Starting position (required when enc is not a Stream)
*/
class Stream {
constructor(enc: Stream | ArrayLike<number> | string, pos?: number);
/** Source data (not copied) */
enc: ArrayLike<number> | string;
/** Current position in the stream */
pos: number;
/**
* Get byte at current position (and increment) or specified position
* @param pos - Read position if specified, else current position (and increment it)
* @returns Byte value at the specified position
* @throws Error if position exceeds stream length
*/
get(pos?: number): number;
/**
* Hexadecimal dump of a specified region of the stream
* @param start - Starting position (included)
* @param end - Ending position (excluded)
* @param type - Output format: 'raw', 'byte', or 'dump' (optional, defaults to 'raw')
* @returns Hexadecimal representation of the region
*/
hexDump(start: number, end: number, type?: 'raw' | 'byte' | 'dump'): string;
/**
* Base64 dump of a specified region of the stream
* @param start - Starting position (included)
* @param end - Ending position (excluded)
* @param type - Output format: 'url' (Base64url) or 'std' (standard Base64)
* @returns Base64 representation of the region
*/
b64Dump(start: number, end: number, type?: 'url' | 'std'): string;
/**
* Parse integer from stream region using ASN.1 INTEGER rules
* @param start - Starting position
* @param end - Ending position
* @returns String representation of the integer (handles big integers)
*/
parseInteger(start: number, end: number): string;
/**
* Parse Object Identifier from stream region
* @param start - Starting position
* @param end - Ending position
* @param maxLength - Maximum length for output (optional)
* @returns OID string in dotted notation (e.g., "1.2.840.113549.1.1.1")
*/
parseOID(start: number, end: number, maxLength?: number): string;
/**
* Parse Relative Object Identifier from stream region
* @param start - Starting position
* @param end - Ending position
* @param maxLength - Maximum length for output (optional)
* @returns Relative OID string
*/
parseRelativeOID(start: number, end: number, maxLength?: number): string;
/**
* Parse time value from stream region (UTCTime or GeneralizedTime)
* @param start - Starting position
* @param end - Ending position
* @param shortYear - true for UTCTime (2-digit year), false for GeneralizedTime (4-digit year)
* @returns Formatted time string
*/
parseTime(start: number, end: number, shortYear: boolean): string;
/**
* Parse UTF-8 string from stream region
* @param start - Starting position
* @param end - Ending position
* @param maxLength - Maximum length for output (optional)
* @returns Object with str (parsed string) and size (byte count) properties
*/
parseStringUTF(start: number, end: number, maxLength?: number): { str: string; size: number };
/**
* Parse ISO/ASCII string from stream region
* @param start - Starting position
* @param end - Ending position
* @param maxLength - Maximum length for output (optional)
* @returns Object with str (parsed string) and size (byte count) properties
*/
parseStringISO(start: number, end: number, maxLength?: number): { str: string; size: number };
/**
* Parse BMP (Basic Multilingual Plane) string from stream region
* @param start - Starting position
* @param end - Ending position
* @param maxLength - Maximum length for output (optional)
* @returns Object with str (parsed string) and size (byte count) properties
*/
parseStringBMP(start: number, end: number, maxLength?: number): { str: string; size: number };
/**
* Parse T.61 string from stream region
* @param start - Starting position
* @param end - Ending position
* @param maxLength - Maximum length for output (optional)
* @returns Object with str (parsed string) and size (byte count) properties
*/
parseStringT61(start: number, end: number, maxLength?: number): { str: string; size: number };
/**
* Parse bit string from stream region
* @param start - Starting position
* @param end - Ending position
* @param maxLength - Maximum length for output (optional)
* @returns Object with str (bit string) and size (bit count) properties
*/
parseBitString(start: number, end: number, maxLength?: number): { str: string; size: number };
/**
* Parse octet string from stream region
* @param start - Starting position
* @param end - Ending position
* @param maxLength - Maximum length for output (optional)
* @returns Object with str (hex representation) and size (byte count) properties
*/
parseOctetString(start: number, end: number, maxLength?: number): { str: string; size: number };
}Usage Examples:
import { Stream } from '@lapo/asn1js';
// Create stream from binary array
const data = [0x02, 0x03, 0x01, 0x00, 0xFF]; // INTEGER 65535
const stream = new Stream(data, 0);
// Read bytes manually
console.log(stream.get()); // 0x02 (INTEGER tag)
console.log(stream.get()); // 0x03 (length)
console.log(stream.pos); // 2
// Parse integer content
const intValue = stream.parseInteger(2, 5);
console.log(intValue); // "65535"
// Hex dump
const hexDump = stream.hexDump(0, 5, 'dump');
console.log(hexDump);
// Output formatted hex dump
// Create stream from string (for text data)
const textData = "Hello World";
const textStream = new Stream(textData, 0);
console.log(textStream.get()); // 72 (ASCII 'H')Utility methods for byte and stream operations.
/**
* Convert a single byte to hexadecimal string representation
* @param b - Byte value (0-255)
* @returns Two-character hexadecimal string (e.g., "A0", "FF")
*/
static Stream.hexByte(b: number): string;Usage Examples:
import { Stream } from '@lapo/asn1js';
// Convert bytes to hex
console.log(Stream.hexByte(255)); // "FF"
console.log(Stream.hexByte(0)); // "00"
console.log(Stream.hexByte(160)); // "A0"
// Use with stream data
const data = [0xDE, 0xAD, 0xBE, 0xEF];
const hexString = data.map(b => Stream.hexByte(b)).join('');
console.log(hexString); // "DEADBEEF"Complex examples showing how to use Stream for manual ASN.1 parsing.
import { Stream, ASN1 } from '@lapo/asn1js';
import { Base64 } from '@lapo/asn1js/base64.js';
// Parse RSA public key manually
const rsaKeyPem = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3YkQOL4OqPlzJGPbhUKZ
...
-----END PUBLIC KEY-----`;
const keyData = Base64.unarmor(rsaKeyPem);
const stream = new Stream(keyData, 0);
// Manual parsing (normally you'd use ASN1.decode)
console.log(stream.get()); // 0x30 (SEQUENCE tag)
const length = stream.get(); // Length byte
// Or use ASN1 for full parsing
const publicKey = ASN1.decode(keyData);
console.log(publicKey.toPrettyString());
// Parse specific OID
const oidBytes = [0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01];
const oidStream = new Stream(oidBytes, 0);
const oidString = oidStream.parseOID(0, oidBytes.length);
console.log(oidString); // "1.2.840.113549.1.1.1" (RSA encryption)
// Parse time values
const timeBytes = [0x31, 0x37, 0x30, 0x39, 0x31, 0x32, 0x31, 0x32, 0x33, 0x30, 0x30, 0x30, 0x5A];
const timeStream = new Stream(timeBytes, 0);
const timeString = timeStream.parseTime(0, timeBytes.length, true);
console.log(timeString); // Formatted time string