JavaScript generic ASN.1 parser (mirror)
at github-101 2.9 kB view raw
1#!/usr/bin/env node 2 3// usage: 4// ./dumpASN1.js filename 5// ./dumpASN1.js data:base64,MDMCAQFjLgQACgEACgEAAgEAAgEAAQEAoA+jDQQFTnRWZXIEBAEAAAAwCgQITmV0bG9nb24=== 6 7import * as fs from 'node:fs'; 8import { Base64 } from './base64.js'; 9import { ASN1 } from './asn1.js'; 10import { Defs } from './defs.js'; 11 12const 13 colYellow = '\x1b[33m', 14 colBlue = '\x1b[34m', 15 colReset = '\x1b[0m', 16 reDataURI = /^data:(?:[a-z-]+[/][a-z.+-]+;)?base64,([A-Za-z0-9+/=\s]+)$/; 17 18function print(value, indent) { 19 if (indent === undefined) indent = ''; 20 const def = value.def; 21 let name = ''; 22 if (def?.type) { 23 if (def.id) name += colBlue + def.id + colReset; 24 if (typeof def.type == 'object' && def.name) name = (name ? name + ' ' : '') + def.name; 25 if (def.mismatch) name = (name ? name + ' ' : '') + '[?]'; 26 if (name) name += ' '; 27 } 28 let s = indent + name + colYellow + value.typeName() + colReset + ' @' + value.stream.pos; 29 if (value.length >= 0) 30 s += '+'; 31 s += value.length; 32 if (value.tag.tagConstructed) 33 s += ' (constructed)'; 34 else if ((value.tag.isUniversal() && ((value.tag.tagNumber == 0x03) || (value.tag.tagNumber == 0x04))) && (value.sub !== null)) 35 s += ' (encapsulates)'; 36 let content = value.content(); 37 if (content) 38 s += ': ' + content.replace(/\n/g, '|'); 39 s += '\n'; 40 if (value.sub !== null) { 41 indent += ' '; 42 for (const subval of value.sub) 43 s += print(subval, indent); 44 } 45 return s; 46} 47 48const filename = process.argv[2]; 49const match = reDataURI.exec(filename); 50let content = match 51 ? Buffer.from(match[1]) 52 : fs.readFileSync(filename); 53try { // try PEM first 54 content = Base64.unarmor(content); 55} catch (e) { // try DER/BER then 56} 57let result = ASN1.decode(content); 58content = null; 59const t0 = performance.now(); 60if (process.argv.length == 5) { 61 Defs.match(result, Defs.moduleAndType(Defs.RFC[process.argv[3]], process.argv[4])); 62} else { 63 const types = Defs.commonTypes 64 .map(type => { 65 const stats = Defs.match(result, type); 66 return { type, match: stats.recognized / stats.total }; 67 }) 68 .sort((a, b) => b.match - a.match); 69 const t1 = performance.now(); 70 console.log('Parsed in ' + (t1 - t0).toFixed(2) + ' ms; possible types:'); 71 for (const t of types) 72 console.log((t.match * 100).toFixed(2).padStart(6) + '% ' + t.type.description); 73 Defs.match(result, types[0].type); 74 // const stats = Defs.match(result, types[0].type); 75 // console.log('Stats:', stats); 76 console.log('Parsed as:', result.def); 77 // const type = searchType(process.argv[2]); 78 // const stats = applyDef(result, type); 79} 80console.log(print(result)); 81// console.log('Stats:', (stats.recognized * 100 / stats.total).toFixed(2) + '%'); 82// // print(result, searchType(process.argv[2]), stats); 83// // console.log('Defs:', stats.defs);