JavaScript generic ASN.1 parser (mirror)

Compare changes

Choose any two refs to compare.

+10
.editorconfig
··· 1 + root = true 2 + end_of_line = lf 3 + max_line_length = 120 4 + 5 + [*.{js,css}] 6 + charset = utf-8 7 + indent_size = 4 8 + indent_style = space 9 + insert_final_newline = true 10 + trim_trailing_whitespace = true
+11 -5
.github/workflows/node.js.yml
··· 12 12 13 13 strategy: 14 14 matrix: 15 - node-version: [ 12.20.0, latest ] 15 + node-version: [ 14.6.0, latest ] 16 16 17 17 steps: 18 - - uses: actions/checkout@v3 18 + - uses: actions/checkout@v4 19 + - name: Use pnpm 20 + uses: pnpm/action-setup@v4 21 + with: 22 + run_install: false 19 23 - name: Use Node.js ${{ matrix.node-version }} 20 - uses: actions/setup-node@v3 24 + uses: actions/setup-node@v4 21 25 with: 22 26 node-version: ${{ matrix.node-version }} 23 - - run: npm test all 24 - - run: npm run lint 27 + cache: pnpm 28 + - run: pnpm install 29 + - run: node test all 30 + - run: pnpm run lint 25 31 if: matrix.node-version == 'latest'
+2 -1
.gitignore
··· 2 2 .DS_Store/ 3 3 .vscode/ 4 4 node_modules/ 5 + dist/ 5 6 package-lock.json 6 - pnpm-lock.yaml 7 7 # Artifacts from release.sh 8 + index-local.html 8 9 sha256sums.asc 9 10 asn1js.zip 10 11 # Artifacts from mirror_to_github.sh
+3 -2
.mtn-ignore
··· 1 1 [.]DS_Store$ 2 2 [.]vscode$ 3 3 node_modules$ 4 + dist$ 4 5 package-lock[.]json 5 - pnpm-lock[.]yaml 6 6 # Artifacts from release.sh 7 + index-local.html 7 8 sha256sums[.]asc 8 9 asn1js[.]zip 9 10 # Artifacts from mirror_to_github.sh 10 11 git-[^.]*[.]txt 11 12 # Artifacts from updateOID.sh 12 13 dumpasn1[.]cfg 13 - # Artifacts from parseRFC.js 14 + # Artifacts from updateRFC.sh / parseRFC.js 14 15 rfc$ 15 16 rfcdef[.]json
+99
.vscode/launch.json
··· 1 + { 2 + // Use IntelliSense to learn about possible attributes. 3 + // Hover to view descriptions of existing attributes. 4 + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 + "version": "0.2.0", 6 + "configurations": [ 7 + { 8 + "type": "node", 9 + "request": "launch", 10 + "name": "test", 11 + "skipFiles": [ 12 + "<node_internals>/**" 13 + ], 14 + "program": "${workspaceFolder}/test.js", 15 + "args": [] 16 + }, 17 + { 18 + "type": "node", 19 + "request": "launch", 20 + "name": "dumpASN1", 21 + "skipFiles": [ 22 + "<node_internals>/**" 23 + ], 24 + "program": "${workspaceFolder}/dumpASN1.js", 25 + "args": [ 26 + "examples/ed25519.cer" 27 + ] 28 + }, 29 + { 30 + "type": "node", 31 + "request": "launch", 32 + "name": "parseRFC", 33 + "skipFiles": [ 34 + "<node_internals>/**" 35 + ], 36 + "program": "${workspaceFolder}/parseRFC.js", 37 + "args": [ 38 + "rfc/rfc4511.txt", 39 + "rfcdef.json" 40 + ] 41 + }, 42 + { 43 + "type": "node", 44 + "request": "launch", 45 + "name": "dumpASN1 X.509", 46 + "skipFiles": [ 47 + "<node_internals>/**" 48 + ], 49 + "program": "${workspaceFolder}/dumpASN1.js", 50 + "args": [ 51 + "examples/ed25519.cer", 52 + "1.3.6.1.5.5.7.0.18", 53 + "Certificate" 54 + ] 55 + }, 56 + { 57 + "type": "node", 58 + "request": "launch", 59 + "name": "dumpASN1 CRL", 60 + "skipFiles": [ 61 + "<node_internals>/**" 62 + ], 63 + "program": "${workspaceFolder}/dumpASN1.js", 64 + "args": [ 65 + "data:base64,MIG9AgEBMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxUUjM0IFNhbXBsZXMxGzAZBgNVBAMTElRSMzQgU2FtcGxlIENBIEtESBcNMTAxMTAyMTczMzMwWhcNMTAxMjAyMTczMzMwWjBIMBYCBTQAAAAIFw0xMDExMDIxNzI4MTNaMBYCBTQAAAAKFw0xMDExMDIxNzMxNDZaMBYCBTQAAAALFw0xMDExMDIxNzMzMjVa", 66 + "1.3.6.1.5.5.7.0.18", 67 + "TBSCertList" 68 + ] 69 + }, 70 + { 71 + "type": "node", 72 + "request": "launch", 73 + "name": "dumpASN1 CMS", 74 + "skipFiles": [ 75 + "<node_internals>/**" 76 + ], 77 + "program": "${workspaceFolder}/dumpASN1.js", 78 + "args": [ 79 + "examples/cms-password.p7m", 80 + "1.2.840.113549.1.9.16.0.14", 81 + "ContentInfo" 82 + ] 83 + }, 84 + { 85 + "type": "node", 86 + "request": "launch", 87 + "name": "dumpASN1 LDAP", 88 + "skipFiles": [ 89 + "<node_internals>/**" 90 + ], 91 + "program": "${workspaceFolder}/dumpASN1.js", 92 + "args": [ 93 + "data:base64,MDMCAQFjLgQACgEACgEAAgEAAgEAAQEAoA+jDQQFTnRWZXIEBAEAAAAwCgQITmV0bG9nb24===", 94 + "1.3.6.1.1.18", 95 + "LDAPMessage" 96 + ] 97 + } 98 + ] 99 + }
+9
.vscode/settings.json
··· 1 + { 2 + "editor.insertSpaces": true, 3 + "editor.tabSize": 8, 4 + "editor.indentSize": 4, 5 + "editor.stickyScroll.enabled": true, 6 + "explorer.excludeGitIgnore": true, 7 + "files.eol": "\n", 8 + "git.openRepositoryInParentFolders": "never" 9 + }
+38
CHANGELOG.md
··· 1 + # ChangeLog 2 + 3 + ## 2.1.1 - 2025-10-24 4 + 5 + ### Changed 6 + 7 + - update dev dependencies 8 + - fix test suite that was reporting no error with empty responses 9 + 10 + ### Added 11 + 12 + - add content length check for BOOLEAN, INTEGER, OID ([GitHub #104](https://github.com/lapo-luchini/asn1js/pull/104)) 13 + 14 + ## 2.1.0 - 2025-08-03 15 + 16 + ### Changed 17 + 18 + - when fields are CHOICEs now both the field name and the choice name are shown (fixes [GitHub #102](https://github.com/lapo-luchini/asn1js/issues/102)) 19 + - upgrade minimum NodeJS version supported from 12.20.0 to 14.6.0 due to usage of ?. and ?? operators in defs.js (ECMAScript 2020); older code is still linted against ECMAScript 2015 for now 20 + 21 + ### Added 22 + 23 + - add tests to check expected decoding 24 + 25 + ## 2.0.6 - 2025-07-29 26 + 27 + ### Added 28 + 29 + - add proper support for standard Base64 (we previously only supported Base64url) (fixes [GitHub #99](https://github.com/lapo-luchini/asn1js/pull/99)) 30 + - improve test harness 31 + 32 + ## 2.0.5 - 2025-04-12 33 + 34 + ### Added 35 + 36 + - add `index-local.html` for local `file://` usage without needing a web server 37 + - add definitions support for `LDAPMessage` 38 + - #TODO continue producing old ChangeLog entries
+1 -1
LICENSE
··· 1 1 ISC License 2 2 3 - Copyright (c) 2008-2024 Lapo Luchini <lapo@lapo.it> 3 + Copyright (c) 2008-2025 Lapo Luchini <lapo@lapo.it> 4 4 5 5 Permission to use, copy, modify, and/or distribute this software for any 6 6 purpose with or without fee is hereby granted, provided that the above
+47 -12
README.md
··· 3 3 4 4 asn1js is a JavaScript generic ASN.1 parser/decoder that can decode any valid ASN.1 DER or BER structures. 5 5 6 - An example page that can decode Base64-encoded (raw base64, PEM armoring and `begin-base64` are recognized) or Hex-encoded (or local files with some browsers) is included and can be used both [online on the official website](https://lapo.it/asn1js/) or [offline (ZIP file)](https://lapo.it/asn1js/asn1js.zip). 6 + An example page that can decode Base64-encoded (raw base64, PEM armoring and `begin-base64` are recognized) or Hex-encoded (or local files with some browsers) is included and can be used both [online on the official website](https://asn1js.eu/) or [offline (ZIP file)](https://lapo.it/asn1js/asn1js.zip) by opening `index-local.html`. 7 7 8 - Usage with `npm` / `yarn` 9 - ------------------------- 8 + Usage with `nodejs` 9 + ------------------- 10 10 11 11 This package can be installed with either npm or yarn via the following commands: 12 12 ··· 17 17 yarn add @lapo/asn1js 18 18 ``` 19 19 20 - Assuming a standard javascript bundler is setup you can import it like so: 20 + You can import the classes like this: 21 21 22 22 ```js 23 - import ASN1 from '@lapo/asn1js'; 23 + import { ASN1 } from '@lapo/asn1js'; 24 24 ``` 25 25 26 26 A submodule of this package can also be imported: 27 27 28 28 ```js 29 - import Hex from '@lapo/asn1js/hex'; 29 + import { Hex } from '@lapo/asn1js/hex.js'; 30 30 ``` 31 31 32 - Unfortunately until [`require(esm)` gets released](https://joyeecheung.github.io/blog/2024/03/18/require-esm-in-node-js/) it is necessary to use async `import()` when used from CommonJS (legacy NodeJS) code. 32 + If your code is still not using ES6 Modules (and is using CommonJS) you can `require` it normally [since NodeJS 22](https://joyeecheung.github.io/blog/2024/03/18/require-esm-in-node-js/) (with parameter `--experimental-require-module`): 33 + 34 + ```js 35 + const 36 + { ASN1 } = require('@lapo/asn1js'), 37 + { Hex } = require('@lapo/asn1js/hex.js'); 38 + console.log(ASN1.decode(Hex.decode('06032B6570')).content()); 39 + ``` 40 + 41 + On older NodeJS you instead need to use async `import`: 42 + 43 + ```js 44 + async function main() { 45 + const 46 + { ASN1 } = await import('@lapo/asn1js'), 47 + { Hex } = await import('@lapo/asn1js/hex.js'); 48 + console.log(ASN1.decode(Hex.decode('06032B6570')).content()); 49 + } 50 + main(); 51 + ``` 33 52 34 53 Usage on the web 35 54 -------------------- ··· 38 57 39 58 ```html 40 59 <script> 41 - import { ASN1} from 'https://unpkg.com/@lapo/asn1js@2.0.0/asn1.js'; 60 + import { ASN1 } from 'https://unpkg.com/@lapo/asn1js@2.0.0/asn1.js'; 42 61 import { Hex } from 'https://unpkg.com/@lapo/asn1js@2.0.0/hex.js'; 43 62 44 63 document.body.innerText = ASN1.decode(Hex.decode('06032B6570')).content(); 45 64 </script> 46 65 ``` 47 66 67 + Local usage 68 + -------------------- 69 + 70 + Since unfortunately ESM modules are not working on `file:` protocol due to [CORS issues](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#other_differences_between_modules_and_standard_scripts), there is a bundled [single-file version working locally](https://asn1js.eu/index-local.html). It doesn't work online (due to [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) restrictions about inline content) but can be saved locally and opened in a browser. 71 + 72 + Usage from CLI 73 + -------------------- 74 + 75 + You can dump an ASN.1 structure from the command line using the following command (no need to even install it): 76 + 77 + ```sh 78 + npx @lapo/asn1js ed25519.cer 79 + ``` 80 + 48 81 ISC license 49 82 ----------- 50 83 51 - ASN.1 JavaScript decoder Copyright (c) 2008-2024 Lapo Luchini <lapo@lapo.it> 84 + ASN.1 JavaScript decoder Copyright (c) 2008-2025 Lapo Luchini <lapo@lapo.it> 52 85 53 86 Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 54 87 ··· 68 101 links 69 102 ----- 70 103 71 - - [official website](https://lapo.it/asn1js/) 72 - - [dedicated domain](https://asn1js.eu/) 73 - - [InDefero tracker](http://idf.lapo.it/p/asn1js/) 104 + - [official website](https://asn1js.eu/) 105 + - [alternate website](https://lapo.it/asn1js/) 106 + - [single-file version working locally](https://asn1js.eu/index-local.html) (just save this link) 107 + - [InDefero tracker](http://idf.lapo.it/p/asn1js/) (currently offline) 74 108 - [GitHub mirror](https://github.com/lapo-luchini/asn1js) 109 + - [ChangeLog on GitHub](https://github.com/lapo-luchini/asn1js/blob/trunk/CHANGELOG.md) 75 110 - [Ohloh code stats](https://www.openhub.net/p/asn1js)
+317 -76
asn1.js
··· 1 1 // ASN.1 JavaScript decoder 2 - // Copyright (c) 2008-2024 Lapo Luchini <lapo@lapo.it> 2 + // Copyright (c) 2008 Lapo Luchini <lapo@lapo.it> 3 3 4 4 // Permission to use, copy, modify, and/or distribute this software for any 5 5 // purpose with or without fee is hereby granted, provided that the above 6 6 // copyright notice and this permission notice appear in all copies. 7 - // 7 + // 8 8 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 9 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 10 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ··· 13 13 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 14 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 15 16 - import { Int10 } from './int10.js'; 17 16 import { oids } from './oids.js'; 18 17 19 18 const ··· 21 20 reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|(-(?:0\d|1[0-2])|[+](?:0\d|1[0-4]))([0-5]\d)?)?$/, 22 21 reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|(-(?:0\d|1[0-2])|[+](?:0\d|1[0-4]))([0-5]\d)?)?$/, 23 22 hexDigits = '0123456789ABCDEF', 24 - b64Safe = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', 23 + b64Std = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', 24 + b64URL = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', 25 25 tableT61 = [ 26 26 ['', ''], 27 27 ['AEIOUaeiou', 'ร€รˆรŒร’ร™ร รจรฌรฒรน'], // Grave ··· 41 41 ['CDELNRSTZcdelnrstz', 'ฤŒฤŽฤšฤฝล‡ล˜ล ลคลฝฤฤฤ›ฤพลˆล™ลกลฅลพ'], // Caron 42 42 ]; 43 43 44 + /** 45 + * Truncates a string to a specified length and adds an ellipsis if needed. 46 + * @param {string} str - The input string to truncate 47 + * @param {number} len - The maximum length of the string 48 + * @returns {string} The truncated string 49 + */ 44 50 function stringCut(str, len) { 45 51 if (str.length > len) 46 52 str = str.substring(0, len) + ellipsis; 47 53 return str; 48 54 } 49 55 56 + /** 57 + * Checks if a string contains only printable characters (ASCII 32-126, plus tab, newline, carriage return) 58 + * @param {string} s - The string to check 59 + * @throws {Error} If an unprintable character is found 60 + */ 50 61 function checkPrintable(s) { 51 62 let i, v; 52 63 for (i = 0; i < s.length; ++i) { ··· 56 67 } 57 68 } 58 69 59 - class Stream { 70 + /** 71 + * Class to manage a stream of bytes, with a zero-copy approach. 72 + * It uses an existing array or binary string and advances a position index. 73 + */ 74 + export class Stream { 60 75 76 + /** 77 + * Creates a new Stream object. 78 + * @param {Stream|array|string} enc data (will not be copied) 79 + * @param {?number} pos starting position (mandatory when `end` is not a Stream) 80 + */ 61 81 constructor(enc, pos) { 62 82 if (enc instanceof Stream) { 63 83 this.enc = enc.enc; 64 84 this.pos = enc.pos; 65 85 } else { 66 - // enc should be an array or a binary string 67 86 this.enc = enc; 68 87 this.pos = pos; 69 88 } 89 + if (typeof this.pos != 'number') 90 + throw new Error('"pos" must be a numeric value'); 91 + // Set up the raw byte access function based on the type of data 92 + if (typeof this.enc == 'string') 93 + this.getRaw = pos => this.enc.charCodeAt(pos); 94 + else if (typeof this.enc[0] == 'number') 95 + this.getRaw = pos => this.enc[pos]; 96 + else 97 + throw new Error('"enc" must be a numeric array or a string'); 70 98 } 99 + 100 + /** 101 + * Get the byte at current position (and increment it) or at a specified position (and avoid moving current position). 102 + * @param {?number} pos read position if specified, else current position (and increment it) 103 + * @returns {number} The byte value at the specified position 104 + */ 71 105 get(pos) { 72 106 if (pos === undefined) 73 107 pos = this.pos++; 74 108 if (pos >= this.enc.length) 75 109 throw new Error('Requesting byte offset ' + pos + ' on a stream of length ' + this.enc.length); 76 - return (typeof this.enc == 'string') ? this.enc.charCodeAt(pos) : this.enc[pos]; 110 + return this.getRaw(pos); 77 111 } 78 - hexByte(b) { 112 + 113 + /** 114 + * Convert a single byte to a hexadecimal string (of length 2). 115 + * @param {number} b - The byte to convert 116 + * @returns {string} Hexadecimal representation of the byte 117 + */ 118 + static hexByte(b) { 79 119 return hexDigits.charAt((b >> 4) & 0xF) + hexDigits.charAt(b & 0xF); 80 120 } 81 - /** Hexadecimal dump. 82 - * @param type 'raw', 'byte' or 'dump' */ 121 + 122 + /** 123 + * Hexadecimal dump of a specified region of the stream. 124 + * @param {number} start - starting position (included) 125 + * @param {number} end - ending position (excluded) 126 + * @param {string} type - 'raw', 'byte' or 'dump' (default) 127 + * @returns {string} Hexadecimal representation of the data 128 + */ 83 129 hexDump(start, end, type = 'dump') { 84 130 let s = ''; 85 131 for (let i = start; i < end; ++i) { 86 132 if (type == 'byte' && i > start) 87 133 s += ' '; 88 - s += this.hexByte(this.get(i)); 134 + s += Stream.hexByte(this.get(i)); 89 135 if (type == 'dump') 90 136 switch (i & 0xF) { 91 137 case 0x7: s += ' '; break; ··· 95 141 } 96 142 return s; 97 143 } 98 - b64Dump(start, end) { 99 - let extra = (end - start) % 3, 100 - s = '', 144 + 145 + /** 146 + * Base64url dump of a specified region of the stream (according to RFC 4648 section 5). 147 + * @param {number} start - starting position (included) 148 + * @param {number} end - ending position (excluded) 149 + * @param {string} type - 'url' (default, section 5 without padding) or 'std' (section 4 with padding) 150 + * @returns {string} Base64 encoded representation of the data 151 + */ 152 + b64Dump(start, end, type = 'url') { 153 + const b64 = type === 'url' ? b64URL : b64Std, 154 + extra = (end - start) % 3; 155 + let s = '', 101 156 i, c; 102 157 for (i = start; i + 2 < end; i += 3) { 103 158 c = this.get(i) << 16 | this.get(i + 1) << 8 | this.get(i + 2); 104 - s += b64Safe.charAt(c >> 18 & 0x3F); 105 - s += b64Safe.charAt(c >> 12 & 0x3F); 106 - s += b64Safe.charAt(c >> 6 & 0x3F); 107 - s += b64Safe.charAt(c & 0x3F); 159 + s += b64.charAt(c >> 18 & 0x3F); 160 + s += b64.charAt(c >> 12 & 0x3F); 161 + s += b64.charAt(c >> 6 & 0x3F); 162 + s += b64.charAt(c & 0x3F); 108 163 } 109 164 if (extra > 0) { 110 165 c = this.get(i) << 16; 111 166 if (extra > 1) c |= this.get(i + 1) << 8; 112 - s += b64Safe.charAt(c >> 18 & 0x3F); 113 - s += b64Safe.charAt(c >> 12 & 0x3F); 114 - if (extra == 2) s += b64Safe.charAt(c >> 6 & 0x3F); 167 + s += b64.charAt(c >> 18 & 0x3F); 168 + s += b64.charAt(c >> 12 & 0x3F); 169 + if (extra == 2) s += b64.charAt(c >> 6 & 0x3F); 170 + if (b64 === b64Std) s += '==='.slice(0, 3 - extra); 115 171 } 116 172 return s; 117 173 } 174 + 175 + /** 176 + * Check if a region of the stream contains only ASCII characters (32-176) 177 + * @param {number} start - starting position (included) 178 + * @param {number} end - ending position (excluded) 179 + * @returns {boolean} True if all characters are ASCII, false otherwise 180 + */ 118 181 isASCII(start, end) { 119 182 for (let i = start; i < end; ++i) { 120 183 let c = this.get(i); ··· 123 186 } 124 187 return true; 125 188 } 189 + 190 + /** 191 + * Parse a region of the stream as an ISO string 192 + * @param {number} start - starting position (included) 193 + * @param {number} end - ending position (excluded) 194 + * @param {number} maxLength - maximum length of the output string 195 + * @returns {Object} Object with size and str properties 196 + */ 126 197 parseStringISO(start, end, maxLength) { 127 198 let s = ''; 128 199 for (let i = start; i < end; ++i) 129 200 s += String.fromCharCode(this.get(i)); 130 201 return { size: s.length, str: stringCut(s, maxLength) }; 131 202 } 203 + 204 + /** 205 + * Parse a region of the stream as a T.61 string 206 + * @param {number} start - starting position (included) 207 + * @param {number} end - ending position (excluded) 208 + * @param {number} maxLength - maximum length of the output string 209 + * @returns {Object} Object with size and str properties 210 + */ 132 211 parseStringT61(start, end, maxLength) { 133 212 // warning: this code is not very well tested so far 134 213 function merge(c, d) { 135 - let t = tableT61[c - 0xC0]; 136 - let i = t[0].indexOf(String.fromCharCode(d)); 214 + const t = tableT61[c - 0xC0]; 215 + const i = t[0].indexOf(String.fromCharCode(d)); 137 216 return (i < 0) ? '\0' : t[1].charAt(i); 138 217 } 139 218 let s = '', c; ··· 150 229 } 151 230 return { size: s.length, str: stringCut(s, maxLength) }; 152 231 } 232 + 233 + /** 234 + * Parse a region of the stream as a UTF-8 string 235 + * @param {number} start - starting position (included) 236 + * @param {number} end - ending position (excluded) 237 + * @param {number} maxLength - maximum length of the output string 238 + * @returns {Object} Object with size and str properties 239 + */ 153 240 parseStringUTF(start, end, maxLength) { 241 + /** 242 + * Helper function to process UTF-8 continuation bytes 243 + * @param {number} c - The continuation byte 244 + * @returns {number} The extracted data bits 245 + */ 154 246 function ex(c) { // must be 10xxxxxx 155 247 if ((c < 0x80) || (c >= 0xC0)) 156 248 throw new Error('Invalid UTF-8 continuation byte: ' + c); 157 249 return (c & 0x3F); 158 250 } 251 + /** 252 + * Helper function to convert a code point to a surrogate pair 253 + * @param {number} cp - The code point to convert 254 + * @returns {string} The surrogate pair as a string 255 + */ 159 256 function surrogate(cp) { 160 257 if (cp < 0x10000) 161 258 throw new Error('UTF-8 overlong encoding, codepoint encoded in 4 bytes: ' + cp); ··· 165 262 } 166 263 let s = ''; 167 264 for (let i = start; i < end; ) { 168 - let c = this.get(i++); 265 + const c = this.get(i++); 169 266 if (c < 0x80) // 0xxxxxxx (7 bit) 170 267 s += String.fromCharCode(c); 171 268 else if (c < 0xC0) ··· 181 278 } 182 279 return { size: s.length, str: stringCut(s, maxLength) }; 183 280 } 281 + 282 + /** 283 + * Parse a region of the stream as a BMP (Basic Multilingual Plane) string 284 + * @param {number} start - starting position (included) 285 + * @param {number} end - ending position (excluded) 286 + * @param {number} maxLength - maximum length of the output string 287 + * @returns {Object} Object with size and str properties 288 + */ 184 289 parseStringBMP(start, end, maxLength) { 185 290 let s = '', hi, lo; 186 291 for (let i = start; i < end; ) { ··· 190 295 } 191 296 return { size: s.length, str: stringCut(s, maxLength) }; 192 297 } 298 + 299 + /** 300 + * Parse a region of the stream as a time string 301 + * @param {number} start - starting position (included) 302 + * @param {number} end - ending position (excluded) 303 + * @param {boolean} shortYear - Whether to parse as short year (2-digit) 304 + * @returns {string} Formatted time string 305 + */ 193 306 parseTime(start, end, shortYear) { 194 307 let s = this.parseStringISO(start, end).str, 195 308 m = (shortYear ? reTimeS : reTimeL).exec(s); ··· 217 330 } 218 331 return s; 219 332 } 333 + 334 + /** 335 + * Parse a region of the stream as an integer 336 + * @param {number} start - starting position (included) 337 + * @param {number} end - ending position (excluded) 338 + * @returns {string} Formatted integer string 339 + */ 220 340 parseInteger(start, end) { 221 341 let v = this.get(start), 222 - neg = (v > 127), 223 - pad = neg ? 255 : 0, 224 - len, 225 342 s = ''; 343 + const neg = (v > 127), 344 + pad = neg ? 255 : 0; 226 345 // skip unuseful bits (not allowed in DER) 227 346 while (v == pad && ++start < end) 228 347 v = this.get(start); 229 - len = end - start; 348 + const len = end - start; 230 349 if (len === 0) 231 350 return neg ? '-1' : '0'; 232 351 // show bit length of huge integers 233 352 if (len > 4) { 234 - s = v; 235 - len <<= 3; 236 - while (((s ^ pad) & 0x80) == 0) { 237 - s <<= 1; 238 - --len; 353 + let v2 = v, 354 + lenBit = len << 3; 355 + while (((v2 ^ pad) & 0x80) == 0) { 356 + v2 <<= 1; 357 + --lenBit; 239 358 } 240 - s = '(' + len + ' bit)\n'; 359 + s = '(' + lenBit + ' bit)\n'; 241 360 } 242 361 // decode the integer 243 362 if (neg) v = v - 256; 244 - let n = new Int10(v); 363 + let n = BigInt(v); 245 364 for (let i = start + 1; i < end; ++i) 246 - n.mulAdd(256, this.get(i)); 247 - return s + n.toString(); 365 + n = (n << 8n) | BigInt(this.get(i)); 366 + return s + n; 248 367 } 368 + 369 + /** 370 + * Parse a region of the stream as a bit string. 371 + * @param {number} start - starting position (included) 372 + * @param {number} end - ending position (excluded) 373 + * @param {number} maxLength - maximum length of the output string 374 + * @returns {Object} Object with size and str properties 375 + */ 249 376 parseBitString(start, end, maxLength) { 250 - let unusedBits = this.get(start); 377 + const unusedBits = this.get(start); 251 378 if (unusedBits > 7) 252 379 throw new Error('Invalid BitString with unusedBits=' + unusedBits); 253 - let lenBit = ((end - start - 1) << 3) - unusedBits, 254 - s = ''; 380 + const lenBit = ((end - start - 1) << 3) - unusedBits; 381 + let s = ''; 255 382 for (let i = start + 1; i < end; ++i) { 256 383 let b = this.get(i), 257 384 skip = (i == end - 1) ? unusedBits : 0; ··· 262 389 } 263 390 return { size: lenBit, str: s }; 264 391 } 392 + 393 + /** 394 + * Parse a region of the stream as an octet string. 395 + * @param {number} start - starting position (included) 396 + * @param {number} end - ending position (excluded) 397 + * @param {number} maxLength - maximum length of the output string 398 + * @returns {Object} Object with size and str properties 399 + */ 265 400 parseOctetString(start, end, maxLength) { 266 - let len = end - start, 267 - s; 268 401 try { 269 - s = this.parseStringUTF(start, end, maxLength); 402 + let s = this.parseStringUTF(start, end, maxLength); 270 403 checkPrintable(s.str); 271 404 return { size: end - start, str: s.str }; 272 - } catch (e) { 273 - // ignore 405 + } catch (ignore) { 406 + // If UTF-8 parsing fails, fall back to hexadecimal dump 274 407 } 408 + const len = end - start; 275 409 maxLength /= 2; // we work in bytes 276 410 if (len > maxLength) 277 411 end = start + maxLength; 278 - s = ''; 412 + let s = ''; 279 413 for (let i = start; i < end; ++i) 280 - s += this.hexByte(this.get(i)); 414 + s += Stream.hexByte(this.get(i)); 281 415 if (len > maxLength) 282 416 s += ellipsis; 283 417 return { size: len, str: s }; 284 418 } 419 + 420 + /** 421 + * Parse a region of the stream as an OID (Object Identifier). 422 + * @param {number} start - starting position (included) 423 + * @param {number} end - ending position (excluded) 424 + * @param {number} maxLength - maximum length of the output string 425 + * @param {boolean} isRelative - Whether the OID is relative 426 + * @returns {string} Formatted OID string 427 + */ 285 428 parseOID(start, end, maxLength, isRelative) { 286 429 let s = '', 287 - n = new Int10(), 430 + n = 0n, 288 431 bits = 0; 289 432 for (let i = start; i < end; ++i) { 290 433 let v = this.get(i); 291 - n.mulAdd(128, v & 0x7F); 434 + // Shift bits and add the lower 7 bits of the byte 435 + n = (n << 7n) | BigInt(v & 0x7F); 292 436 bits += 7; 437 + // If the most significant bit is 0, this is the last byte of the OID component 293 438 if (!(v & 0x80)) { // finished 439 + // If this is the first component, handle it specially 294 440 if (s === '') { 295 - n = n.simplify(); 296 441 if (isRelative) { 297 - s = (n instanceof Int10) ? n.toString() : '' + n; 298 - } else if (n instanceof Int10) { 299 - n.sub(80); 300 - s = '2.' + n.toString(); 442 + s = n.toString(); 301 443 } else { 302 - let m = n < 80 ? n < 40 ? 0 : 1 : 2; 303 - s = m + '.' + (n - m * 40); 444 + let m = n < 80 ? n < 40 ? 0n : 1n : 2n; 445 + s = m + '.' + (n - m * 40n); 304 446 } 305 447 } else 306 - s += '.' + n.toString(); 448 + s += '.' + n; 307 449 if (s.length > maxLength) 308 450 return stringCut(s, maxLength); 309 - n = new Int10(); 451 + n = 0n; 310 452 bits = 0; 311 453 } 312 454 } 313 455 if (bits > 0) 314 456 s += '.incomplete'; 457 + // If OIDs mapping is available and the OID is absolute, try to resolve it 315 458 if (typeof oids === 'object' && !isRelative) { 316 459 let oid = oids[s]; 317 460 if (oid) { ··· 322 465 } 323 466 return s; 324 467 } 468 + 469 + /** 470 + * Parse a region of the stream as a relative OID (Object Identifier). 471 + * @param {number} start - starting position (included) 472 + * @param {number} end - ending position (excluded) 473 + * @param {number} maxLength - maximum length of the output string 474 + * @returns {string} Formatted relative OID string 475 + */ 325 476 parseRelativeOID(start, end, maxLength) { 326 477 return this.parseOID(start, end, maxLength, true); 327 478 } ··· 354 505 this.tagConstructed = ((buf & 0x20) !== 0); 355 506 this.tagNumber = buf & 0x1F; 356 507 if (this.tagNumber == 0x1F) { // long tag 357 - let n = new Int10(); 508 + let n = 0n; 358 509 do { 359 510 buf = stream.get(); 360 - n.mulAdd(128, buf & 0x7F); 511 + n = (n << 7n) | BigInt(buf & 0x7F); 361 512 } while (buf & 0x80); 362 - this.tagNumber = n.simplify(); 513 + this.tagNumber = n <= Number.MAX_SAFE_INTEGER ? Number(n) : n; 363 514 } 364 515 } 365 516 isUniversal() { ··· 370 521 } 371 522 } 372 523 524 + /** 525 + * ASN1 class for parsing ASN.1 encoded data. 526 + * Instances of this class represent an ASN.1 element and provides methods to parse and display its content. 527 + */ 373 528 export class ASN1 { 529 + /** 530 + * Creates an ASN1 parser object. 531 + * @param {Stream} stream - The stream containing the ASN.1 data. 532 + * @param {number} header - The header length. 533 + * @param {number} length - The length of the data. 534 + * @param {ASN1Tag} tag - The ASN.1 tag. 535 + * @param {number} tagLen - The length of the tag. 536 + * @param {Array} sub - The sub-elements. 537 + */ 374 538 constructor(stream, header, length, tag, tagLen, sub) { 375 539 if (!(tag instanceof ASN1Tag)) throw new Error('Invalid tag value.'); 376 540 this.stream = stream; ··· 380 544 this.tagLen = tagLen; 381 545 this.sub = sub; 382 546 } 547 + 548 + /** 549 + * Get the type name of the ASN.1 element. 550 + * @returns {string} The type name. 551 + */ 383 552 typeName() { 384 553 switch (this.tag.tagClass) { 385 554 case 0: // universal ··· 419 588 case 3: return 'Private_' + this.tag.tagNumber.toString(); 420 589 } 421 590 } 422 - /** A string preview of the content (intended for humans). */ 591 + 592 + /** 593 + * Get a string preview of the content (intended for humans). 594 + * @param {number} maxLength - The maximum length of the content. 595 + * @returns {string|null} The content preview or null if not supported. 596 + */ 423 597 content(maxLength) { 424 598 if (this.tag === undefined) 425 599 return null; 426 600 if (maxLength === undefined) 427 601 maxLength = Infinity; 428 - let content = this.posContent(), 602 + const content = this.posContent(), 429 603 len = Math.abs(this.length); 430 604 if (!this.tag.isUniversal()) { 431 605 if (this.sub !== null) ··· 435 609 } 436 610 switch (this.tag.tagNumber) { 437 611 case 0x01: // BOOLEAN 612 + if (len != 1) return 'invalid length ' + len; 438 613 return (this.stream.get(content) === 0) ? 'false' : 'true'; 439 614 case 0x02: // INTEGER 615 + if (len < 1) return 'invalid length ' + len; 440 616 return this.stream.parseInteger(content, content + len); 441 617 case 0x03: { // BIT_STRING 442 618 let d = recurse(this, 'parseBitString', maxLength); ··· 448 624 } 449 625 //case 0x05: // NULL 450 626 case 0x06: // OBJECT_IDENTIFIER 627 + if (len < 1) return 'invalid length ' + len; // pgut001's dumpasn1.c enforces a minimum lenght of 3 451 628 return this.stream.parseOID(content, content + len, maxLength); 452 629 //case 0x07: // ObjectDescriptor 453 630 //case 0x08: // EXTERNAL ··· 484 661 } 485 662 return null; 486 663 } 664 + 665 + /** 666 + * Get a string representation of the ASN.1 element. 667 + * @returns {string} The string representation. 668 + */ 487 669 toString() { 488 670 return this.typeName() + '@' + this.stream.pos + '[header:' + this.header + ',length:' + this.length + ',sub:' + ((this.sub === null) ? 'null' : this.sub.length) + ']'; 489 671 } 672 + 673 + /** 674 + * Get a pretty string representation of the ASN.1 element. 675 + * @param {string} indent - The indentation string. 676 + * @returns {string} The pretty string representation. 677 + */ 490 678 toPrettyString(indent) { 491 679 if (indent === undefined) indent = ''; 492 - let s = indent + this.typeName() + ' @' + this.stream.pos; 680 + let s = indent; 681 + if (this.def) { 682 + if (this.def.id) 683 + s += this.def.id + ' '; 684 + if (this.def.name && this.def.name != this.typeName().replace(/_/g, ' ')) 685 + s+= this.def.name + ' '; 686 + if (this.def.mismatch) 687 + s += '[?] '; 688 + } 689 + s += this.typeName() + ' @' + this.stream.pos; 493 690 if (this.length >= 0) 494 691 s += '+'; 495 692 s += this.length; ··· 508 705 } 509 706 return s; 510 707 } 708 + 709 + /** 710 + * Get the starting position of the element in the stream. 711 + * @returns {number} The starting position. 712 + */ 511 713 posStart() { 512 714 return this.stream.pos; 513 715 } 716 + 717 + /** 718 + * Get the position of the content in the stream. 719 + * @returns {number} The content position. 720 + */ 514 721 posContent() { 515 722 return this.stream.pos + this.header; 516 723 } 724 + 725 + /** 726 + * Get the ending position of the element in the stream. 727 + * @returns {number} The ending position. 728 + */ 517 729 posEnd() { 518 730 return this.stream.pos + this.header + Math.abs(this.length); 519 731 } 520 - /** Position of the length. */ 732 + 733 + /** 734 + * Get the position of the length in the stream. 735 + * @returns {number} The length position. 736 + */ 521 737 posLen() { 522 738 return this.stream.pos + this.tagLen; 523 739 } 524 - /** Hexadecimal dump of the node. 525 - * @param type 'raw', 'byte' or 'dump' */ 740 + 741 + /** 742 + * Get a hexadecimal dump of the node. 743 + * @param {string} [type='raw'] - The dump type: 'raw', 'byte', or 'dump'. 744 + * @returns {string} The hexadecimal dump. 745 + */ 526 746 toHexString(type = 'raw') { 527 747 return this.stream.hexDump(this.posStart(), this.posEnd(), type); 528 748 } 529 - /** Base64 dump of the node. */ 530 - toB64String() { 531 - return this.stream.b64Dump(this.posStart(), this.posEnd()); 749 + 750 + /** 751 + * Get a base64url dump of the node (according to RFC 4648 section 5). 752 + * @param {string} [type='url'] - The dump type: 'url' (section 5 without padding) or 'std' (section 4 with padding). 753 + * @returns {string} The base64 encoded representation. 754 + */ 755 + toB64String(type = 'url') { 756 + return this.stream.b64Dump(this.posStart(), this.posEnd(), type); 532 757 } 758 + 759 + /** 760 + * Decode the length field of an ASN.1 element. 761 + * @param {Stream} stream - The stream to read from. 762 + * @returns {number|null} The decoded length, or null for indefinite length. 763 + * @throws {Error} If the length is invalid or exceeds 48 bits. 764 + */ 533 765 static decodeLength(stream) { 534 - let buf = stream.get(), 766 + const buf = stream.get(), 535 767 len = buf & 0x7F; 536 768 if (len == buf) // first bit was 0, short form 537 769 return len; 538 770 if (len === 0) // long form with length 0 is a special case 539 771 return null; // undefined length 540 - if (len > 6) // no reason to use Int10, as it would be a huge buffer anyways 772 + if (len > 6) // no reason to use BigInt, as it would be a huge buffer anyways 541 773 throw new Error('Length over 48 bits not supported at position ' + (stream.pos - 1)); 542 - buf = 0; 774 + let value = 0; 543 775 for (let i = 0; i < len; ++i) 544 - buf = (buf * 256) + stream.get(); 545 - return buf; 776 + value = (value << 8) | stream.get(); 777 + return value; 546 778 } 779 + 780 + /** 781 + * Decode an ASN.1 element from a stream. 782 + * @param {Stream|array|string} stream - The input data. 783 + * @param {number} [offset=0] - The offset to start decoding from. 784 + * @param {Function} [type=ASN1] - The class to instantiate. 785 + * @returns {ASN1} The decoded ASN.1 element. 786 + * @throws {Error} If the decoding fails. 787 + */ 547 788 static decode(stream, offset, type = ASN1) { 548 789 if (!(type == ASN1 || type.prototype instanceof ASN1)) 549 790 throw new Error('Must pass a class that extends ASN1'); ··· 601 842 throw new Error('Unable to parse content: ' + e); 602 843 } 603 844 } 604 - } catch (e) { 845 + } catch (ignore) { 605 846 // but silently ignore when they don't 606 847 sub = null; 607 848 //DEBUG console.log('Could not decode structure at ' + start + ':', e);
+8 -7
base64.js
··· 1 1 // Base64 JavaScript decoder 2 - // Copyright (c) 2008-2024 Lapo Luchini <lapo@lapo.it> 2 + // Copyright (c) 2008 Lapo Luchini <lapo@lapo.it> 3 3 4 4 // Permission to use, copy, modify, and/or distribute this software for any 5 5 // purpose with or without fee is hereby granted, provided that the above 6 6 // copyright notice and this permission notice appear in all copies. 7 - // 7 + // 8 8 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 9 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 10 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ··· 31 31 decoder[b64.charCodeAt(i)] = i; 32 32 for (i = 0; i < ignore.length; ++i) 33 33 decoder[ignore.charCodeAt(i)] = -1; 34 - // RFC 3548 URL & file safe encoding 34 + // also support decoding Base64url (RFC 4648 section 5) 35 35 decoder['-'.charCodeAt(0)] = decoder['+'.charCodeAt(0)]; 36 36 decoder['_'.charCodeAt(0)] = decoder['/'.charCodeAt(0)]; 37 37 } ··· 75 75 76 76 static pretty(str) { 77 77 // fix padding 78 - if (str.length % 4 > 0) 79 - str = (str + '===').slice(0, str.length + str.length % 4); 80 - // convert RFC 3548 to standard Base64 78 + let pad = 4 - str.length % 4; 79 + if (pad < 4) 80 + str += '==='.slice(0, pad); 81 + // convert Base64url (RFC 4648 section 5) to standard Base64 (RFC 4648 section 4) 81 82 str = str.replace(/-/g, '+').replace(/_/g, '/'); 82 83 // 80 column width 83 - return str.replace(/(.{80})/g, '$1\n'); 84 + return str.replace(/.{80}/g, '$&\n'); 84 85 } 85 86 86 87 static unarmor(a) {
+1 -1
check.sh
··· 1 1 #!/bin/sh 2 - type gsha256sum >/dev/null && SHA256=gsha256sum || SHA256=sha256sum 2 + type gsha256sum >/dev/null 2>/dev/null && SHA256=gsha256sum || SHA256=sha256sum 3 3 gpg --verify -o - sha256sums.asc | $SHA256 -c --quiet
+10 -7
context.js
··· 10 10 const type = node.asn1.typeName(); 11 11 const valueEnabled = type != 'SET' && type != 'SEQUENCE'; 12 12 node.onclick = function (event) { 13 + // do not show the menu in case of clicking the icon 14 + if (event.srcElement.nodeName != 'SPAN') return; 13 15 contextMenu.style.left = event.pageX + 'px'; 14 16 contextMenu.style.top = event.pageY + 'px'; 15 17 contextMenu.style.visibility = 'visible'; 16 18 contextMenu.node = this; 17 19 btnCopyValue.style.display = valueEnabled ? 'block' : 'none'; 20 + event.preventDefault(); 18 21 event.stopPropagation(); 19 22 }; 20 - }; 23 + } 21 24 22 - function close() { 25 + function close(event) { 23 26 contextMenu.style.visibility = 'hidden'; 27 + event.stopPropagation(); 24 28 } 25 29 26 30 contextMenu.onmouseleave = close; 27 31 28 32 btnCopyHex.onclick = function (event) { 29 - event.stopPropagation(); 30 33 navigator.clipboard.writeText(contextMenu.node.asn1.toHexString('byte')); 31 - close(); 34 + close(event); 32 35 }; 33 36 34 37 btnCopyB64.onclick = function (event) { 35 38 event.stopPropagation(); 36 39 navigator.clipboard.writeText(contextMenu.node.asn1.toB64String()); 37 - close(); 40 + close(event); 38 41 }; 39 42 40 43 btnCopyTree.onclick = function (event) { 41 44 event.stopPropagation(); 42 45 navigator.clipboard.writeText(contextMenu.node.asn1.toPrettyString()); 43 - close(); 46 + close(event); 44 47 }; 45 48 46 49 btnCopyValue.onclick = function (event) { 47 50 event.stopPropagation(); 48 51 navigator.clipboard.writeText(contextMenu.node.asn1.content()); 49 - close(); 52 + close(event); 50 53 };
+29 -14
defs.js
··· 1 1 // ASN.1 RFC definitions matcher 2 - // Copyright (c) 2023-2024 Lapo Luchini <lapo@lapo.it> 2 + // Copyright (c) 2023 Lapo Luchini <lapo@lapo.it> 3 3 4 4 // Permission to use, copy, modify, and/or distribute this software for any 5 5 // purpose with or without fee is hereby granted, provided that the above 6 6 // copyright notice and this permission notice appear in all copies. 7 - // 7 + // 8 8 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 9 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 10 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ··· 23 23 try { 24 24 // hope current OIDs contain the type name (will need to parse from RFC itself) 25 25 def = Defs.searchType(firstUpper(stats.defs[def.definedBy][1])); 26 - } catch (e) { /*ignore*/ } 26 + } catch (ignore) { /*ignore*/ } 27 27 while (def?.type == 'defined' || def?.type?.type == 'defined') { 28 28 const name = def?.type?.type ? def.type.name : def.name; 29 29 def = Object.assign({}, def); 30 30 def.type = Defs.searchType(name).type; 31 31 } 32 - if (def?.type?.name == 'CHOICE') { 33 - for (let c of def.type.content) { 32 + if (def?.name == 'CHOICE' || def?.type?.name == 'CHOICE') { 33 + for (let c of def.content ?? def.type.content) { 34 34 if (tn != c.type.name && tn != c.name) 35 35 c = translate(c); 36 36 if (tn == c.type.name || tn == c.name) { 37 37 def = Object.assign({}, def); 38 + if (c.id) // show the CHOICE id, but add it to existing one if present 39 + def.id = def.id ? def.id + ' ' + c.id : c.id; 38 40 def.type = c.type.name ? c.type : c; 39 41 break; 40 42 } ··· 63 65 // return r.types[name]; 64 66 return Defs.moduleAndType(mod, name); 65 67 } 66 - throw 'Type not found: ' + name; 68 + throw new Error('Type not found: ' + name); 67 69 } 68 70 69 71 static match(value, def, stats = { total: 0, recognized: 0, defs: {} }) { 70 72 value.def = {}; 71 - let tn = value.typeName().replaceAll('_', ' '); 73 + let tn = value.typeName().replace(/_/g, ' '); 72 74 def = translate(def, tn, stats); 73 75 ++stats.total; 74 76 if (def?.type) { ··· 89 91 if (def.typeOf) 90 92 type = def.content[0]; 91 93 else { 92 - let tn = subval.typeName().replaceAll('_', ' '); 93 - do { 94 + let tn = subval.typeName().replace(/_/g, ' '); 95 + for (;;) { 94 96 type = def.content[j++]; 95 - // type = translate(type, tn); 97 + if (!type || typeof type != 'object') break; 96 98 if (type?.type?.type) 97 - type = type.type; 98 - } while (type && typeof type == 'object' && ('optional' in type || 'default' in type) && type.name != 'ANY' && type.name != tn); 99 + // type = type.type; 100 + type = Object.assign({}, type.type, {id: type.id}); 101 + if (type.type == 'defined') { 102 + let t2 = translate(type, tn); 103 + if (t2.type.name == tn) break; // exact match 104 + if (t2.type.name == 'ANY') break; // good enough 105 + } 106 + if (type.name == tn) break; // exact match 107 + if (type.name == 'ANY') break; // good enough 108 + if (!('optional' in type || 'default' in type)) break; 109 + } 99 110 if (type?.type == 'builtin' || type?.type == 'defined') { 100 111 let v = subval.content(); 101 112 if (typeof v == 'string') ··· 104 115 } else if (type?.definedBy && stats.defs?.[type.definedBy]?.[1]) { // hope current OIDs contain the type name (will need to parse from RFC itself) 105 116 try { 106 117 type = Defs.searchType(firstUpper(stats.defs[type.definedBy][1])); 107 - } catch (e) { /*ignore*/ } 118 + } catch (ignore) { /*ignore*/ } 108 119 } 109 120 } 110 121 } ··· 119 130 Defs.RFC = rfcdef; 120 131 121 132 Defs.commonTypes = [ 122 - [ 'X.509 certificate', '1.3.6.1.5.5.7.0.18', 'Certificate' ], 133 + [ 'X.509 certificate', '1.3.6.1.5.5.7.0.18', 'Certificate' ], 134 + [ 'X.509 public key info', '1.3.6.1.5.5.7.0.18', 'SubjectPublicKeyInfo' ], 135 + [ 'X.509 certificate revocation list', '1.3.6.1.5.5.7.0.18', 'CertificateList' ], 123 136 [ 'CMS / PKCS#7 envelope', '1.2.840.113549.1.9.16.0.14', 'ContentInfo' ], 124 137 [ 'PKCS#1 RSA private key', '1.2.840.113549.1.1.0.1', 'RSAPrivateKey' ], 125 138 [ 'PKCS#8 encrypted private key', '1.2.840.113549.1.8.1.1', 'EncryptedPrivateKeyInfo' ], 126 139 [ 'PKCS#8 private key', '1.2.840.113549.1.8.1.1', 'PrivateKeyInfo' ], 127 140 [ 'PKCS#10 certification request', '1.2.840.113549.1.10.1.1', 'CertificationRequest' ], 128 141 [ 'CMP PKI Message', '1.3.6.1.5.5.7.0.16', 'PKIMessage' ], 142 + [ 'LDAP Message', '1.3.6.1.1.18', 'LDAPMessage' ], 143 + [ 'Time Stamp Request', '1.3.6.1.5.5.7.0.13', 'TimeStampReq' ], 129 144 ].map(arr => ({ description: arr[0], ...Defs.moduleAndType(rfcdef[arr[1]], arr[2]) }));
+33 -23
dom.js
··· 1 1 // ASN.1 JavaScript decoder 2 - // Copyright (c) 2008-2024 Lapo Luchini <lapo@lapo.it> 2 + // Copyright (c) 2008 Lapo Luchini <lapo@lapo.it> 3 3 4 4 // Permission to use, copy, modify, and/or distribute this software for any 5 5 // purpose with or without fee is hereby granted, provided that the above 6 6 // copyright notice and this permission notice appear in all copies. 7 - // 7 + // 8 8 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 9 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 10 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ··· 24 24 ellipsis: '\u2026', 25 25 tag: function (tagName, className, text) { 26 26 let t = document.createElement(tagName); 27 - t.className = className; 27 + if (className) t.className = className; 28 28 if (text) t.innerText = text; 29 29 return t; 30 30 }, ··· 56 56 toDOM(spaces) { 57 57 spaces = spaces || ''; 58 58 let isOID = (typeof oids === 'object') && (this.tag.isUniversal() && (this.tag.tagNumber == 0x06) || (this.tag.tagNumber == 0x0D)); 59 - let node = DOM.tag('div', 'node'); 59 + let node = DOM.tag('li'); 60 60 node.asn1 = this; 61 - let head = DOM.tag('div', 'head'); 62 - head.appendChild(DOM.tag('span', 'spaces', spaces)); 61 + let head = DOM.tag('span', 'head'); 63 62 const typeName = this.typeName().replace(/_/g, ' '); 64 63 if (this.def) { 65 64 if (this.def.id) { ··· 111 110 content = content.replace(/</g, '&lt;'); 112 111 content = content.replace(/\n/g, '<br>'); 113 112 } 114 - node.appendChild(head); 115 - this.node = node; 113 + // add the li and details section for this node 114 + let contentNode; 115 + let childNode; 116 + if (this.sub !== null) { 117 + let details = DOM.tag('details'); 118 + details.setAttribute('open', ''); 119 + node.appendChild(details); 120 + let summary = DOM.tag('summary', 'node'); 121 + details.appendChild(summary); 122 + summary.appendChild(head); 123 + contentNode = summary; 124 + childNode = details; 125 + } else { 126 + contentNode = node; 127 + contentNode.classList.add('node'); 128 + contentNode.appendChild(head); 129 + } 130 + this.node = contentNode; 116 131 this.head = head; 117 132 let value = DOM.tag('div', 'value'); 118 133 let s = 'Offset: ' + this.stream.pos + '<br>'; ··· 135 150 } 136 151 } 137 152 value.innerHTML = s; 138 - node.appendChild(value); 139 - let sub = DOM.tag('div', 'sub'); 153 + contentNode.appendChild(value); 140 154 if (this.sub !== null) { 155 + let sub = DOM.tag('ul'); 156 + childNode.appendChild(sub); 141 157 spaces += '\xA0 '; 142 158 for (let i = 0, max = this.sub.length; i < max; ++i) 143 159 sub.appendChild(this.sub[i].toDOM(spaces)); 144 160 } 145 - node.appendChild(sub); 146 - head.onclick = function () { 147 - node.className = (node.className == 'node collapsed') ? 'node' : 'node collapsed'; 148 - }; 161 + bindContextMenu(node); 149 162 return node; 150 163 } 151 164 fakeHover(current) { 152 - this.node.className += ' hover'; 165 + this.node.classList.add('hover'); 153 166 if (current) 154 - this.head.className += ' hover'; 167 + this.head.classList.add('hover'); 155 168 } 156 169 fakeOut(current) { 157 - let re = / ?hover/; 158 - this.node.className = this.node.className.replace(re, ''); 170 + this.node.classList.remove('hover'); 159 171 if (current) 160 - this.head.className = this.head.className.replace(re, ''); 172 + this.head.classList.remove('hover'); 161 173 } 162 174 toHexDOM_sub(node, className, stream, start, end) { 163 175 if (start >= end) ··· 172 184 this.head.onmouseover = function () { this.hexNode.className = 'hexCurrent'; }; 173 185 this.head.onmouseout = function () { this.hexNode.className = 'hex'; }; 174 186 node.asn1 = this; 175 - node.onmouseover = function () { 187 + node.onmouseover = function (event) { 176 188 let current = !root.selected; 177 189 if (current) { 178 190 root.selected = this.asn1; 179 191 this.className = 'hexCurrent'; 180 192 } 181 193 this.asn1.fakeHover(current); 194 + event.stopPropagation(); 182 195 }; 183 196 node.onmouseout = function () { 184 197 let current = (root.selected == this.asn1); ··· 202 215 node.appendChild(skip); 203 216 } 204 217 } 205 - // set the current start and end position as an attribute at the node to know the selected area 206 - node.setAttribute('pos', this.posStart()); 207 - node.setAttribute('end', this.posEnd()); 208 218 this.toHexDOM_sub(node, 'tag', this.stream, this.posStart(), this.posLen()); 209 219 this.toHexDOM_sub(node, (this.length >= 0) ? 'dlen' : 'ulen', this.stream, this.posLen(), this.posContent()); 210 220 if (this.sub === null) {
+32 -19
dumpASN1.js
··· 1 1 #!/usr/bin/env node 2 2 3 + // usage: 4 + // ./dumpASN1.js filename 5 + // ./dumpASN1.js data:base64,MDMCAQFjLgQACgEACgEAAgEAAgEAAQEAoA+jDQQFTnRWZXIEBAEAAAAwCgQITmV0bG9nb24=== 6 + 3 7 import * as fs from 'node:fs'; 4 8 import { Base64 } from './base64.js'; 5 9 import { ASN1 } from './asn1.js'; ··· 8 12 const 9 13 colYellow = '\x1b[33m', 10 14 colBlue = '\x1b[34m', 11 - colReset = '\x1b[0m'; 15 + colReset = '\x1b[0m', 16 + reDataURI = /^data:(?:[a-z-]+[/][a-z.+-]+;)?base64,([A-Za-z0-9+/=\s]+)$/; 12 17 13 18 function print(value, indent) { 14 19 if (indent === undefined) indent = ''; ··· 40 45 return s; 41 46 } 42 47 43 - let content = fs.readFileSync(process.argv[2]); 48 + const filename = process.argv[2]; 49 + const match = reDataURI.exec(filename); 50 + let content = match 51 + ? Buffer.from(match[1]) 52 + : fs.readFileSync(filename); 44 53 try { // try PEM first 45 54 content = Base64.unarmor(content); 46 - } catch (e) { // try DER/BER then 55 + } catch (ignore) { // try DER/BER then 47 56 } 48 57 let result = ASN1.decode(content); 49 58 content = null; 50 59 const t0 = performance.now(); 51 - const types = Defs.commonTypes 52 - .map(type => { 53 - const stats = Defs.match(result, type); 54 - return { type, match: stats.recognized / stats.total }; 55 - }) 56 - .sort((a, b) => b.match - a.match); 57 - const t1 = performance.now(); 58 - console.log('Parsed in ' + (t1 - t0).toFixed(2) + ' ms; possible types:'); 59 - for (const t of types) 60 - console.log((t.match * 100).toFixed(2).padStart(6) + '% ' + t.type.description); 61 - Defs.match(result, types[0].type); 62 - // const stats = Defs.match(result, types[0].type); 63 - // console.log('Stats:', stats); 64 - console.log('Parsed as:', result.def); 65 - // const type = searchType(process.argv[2]); 66 - // const stats = applyDef(result, type); 60 + if (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 + } 67 80 console.log(print(result)); 68 81 // console.log('Stats:', (stats.recognized * 100 / stats.total).toFixed(2) + '%'); 69 82 // // print(result, searchType(process.argv[2]), stats);
+63
eslint.config.js
··· 1 + import globals from 'globals'; 2 + import js from '@eslint/js'; 3 + 4 + export default [ 5 + js.configs.recommended, 6 + { 7 + languageOptions: { 8 + globals: { 9 + ...globals.browser, 10 + ...globals.node, 11 + Uint8Array: 'readonly', 12 + }, 13 + ecmaVersion: 2020, 14 + }, 15 + rules: { 16 + indent: ['error', 4], 17 + 'no-trailing-spaces': ['error'], 18 + 'linebreak-style': ['error', 'unix'], 19 + 'eol-last': ['error', 'always'], 20 + semi: ['warn', 'always'], 21 + quotes: [ 'error', 'single', { 22 + avoidEscape: true, 23 + }], 24 + 'no-var': ['warn'], 25 + 'comma-dangle': ['error', 'always-multiline'], 26 + 'no-unused-vars': ['error', { 27 + caughtErrorsIgnorePattern: 'ignore', 28 + }], 29 + }, 30 + }, 31 + { 32 + files: ['oids.js'], 33 + rules: { 34 + indent: 'off', 35 + quotes: ['warn', 'double'], 36 + }, 37 + }, 38 + { 39 + files: ['tags.js', 'rfcdef.js'], 40 + rules: { 41 + indent: [ 42 + 'error', 43 + 2, 44 + { 45 + ignoredNodes: [ 46 + "Program > ExpressionStatement > CallExpression > FunctionExpression > BlockStatement > ExpressionStatement[directive='use strict']:first-child", 47 + ], 48 + }, 49 + ], 50 + 'comma-dangle': 'off', 51 + quotes: ['warn', 'double'], 52 + }, 53 + }, 54 + { 55 + files: ['test.js', 'parseRFC.js', 'dumpASN1.js', 'testDefs.js', 'eslint.config.js'], 56 + languageOptions: { 57 + ecmaVersion: 'latest', 58 + }, 59 + rules: { 60 + strict: ['error', 'global'], 61 + }, 62 + }, 63 + ];
+9
examples/cms-password.p7m
··· 1 + This is a PKCS#7/CMS encrypted with passwod. 2 + $ echo content | openssl cms -encrypt -pwri_password test -aes256 -outform pem -out examples/cms-password.p7m 3 + -----BEGIN CMS----- 4 + MIHYBgkqhkiG9w0BBwOggcowgccCAQMxgYOjgYACAQCgGwYJKoZIhvcNAQUMMA4E 5 + CED/DSxXMtH6AgIIADAsBgsqhkiG9w0BCRADCTAdBglghkgBZQMEASoEEDIQbJMC 6 + Sfb3LpwHduj/meQEMKwrwq5M4V0stztm6OUTAsFY2zKDY20SApwSEeEcAh9TM42E 7 + 1palnHeqHTBpC8pIpjA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBByt+scPrdM 8 + giR7WUOJyB3hgBDcD3UDMtZSep8X/3yy1/Yq 9 + -----END CMS-----
+12
examples/crl-rfc5280.b64
··· 1 + CRL example from RFC5280 as found here: 2 + https://csrc.nist.gov/projects/pki-testing/sample-certificates-and-crls 3 + 4 + begin-base64 644 crl-rfc5280.der 5 + MIIBYDCBygIBATANBgkqhkiG9w0BAQUFADBDMRMwEQYKCZImiZPyLGQBGRYDY29tMRcwFQYKCZIm 6 + iZPyLGQBGRYHZXhhbXBsZTETMBEGA1UEAxMKRXhhbXBsZSBDQRcNMDUwMjA1MTIwMDAwWhcNMDUw 7 + MjA2MTIwMDAwWjAiMCACARIXDTA0MTExOTE1NTcwM1owDDAKBgNVHRUEAwoBAaAvMC0wHwYDVR0j 8 + BBgwFoAUCGivhTPIOUp6+IKTjnBqSiCELDIwCgYDVR0UBAMCAQwwDQYJKoZIhvcNAQEFBQADgYEA 9 + ItwYffcIzsx10NBqm60Q9HYjtIFutW2+DvsVFGzIF20f7pAXom9g5L2qjFXejoRvkvifEBInr0rU 10 + L4XiNkR9qqNMJTgV/wD9Pn7uPSYS69jnK2LiK8NGgO94gtEVxtCccmrLznrtZ5mLbnCBfUNCdMGm 11 + r8FVF6IzTNYGmCuk/C4= 12 + ====
+45
examples/crl-rfc5280.b64.dump
··· 1 + CertificateList SEQUENCE @0+352 (constructed): (3 elem) 2 + tbsCertList TBSCertList SEQUENCE @4+202 (constructed): (7 elem) 3 + version Version INTEGER @7+1: 1 4 + signature AlgorithmIdentifier SEQUENCE @10+13 (constructed): (2 elem) 5 + algorithm OBJECT_IDENTIFIER @12+9: 1.2.840.113549.1.1.5|sha1WithRSAEncryption|PKCS #1 6 + parameters ANY NULL @23+0 7 + issuer rdnSequence Name SEQUENCE @25+67 (constructed): (3 elem) 8 + RelativeDistinguishedName SET @27+19 (constructed): (1 elem) 9 + AttributeTypeAndValue SEQUENCE @29+17 (constructed): (2 elem) 10 + type AttributeType OBJECT_IDENTIFIER @31+10: 0.9.2342.19200300.100.1.25|domainComponent|Men are from Mars, this OID is from Pluto 11 + value AttributeValue [?] IA5String @43+3: com 12 + RelativeDistinguishedName SET @48+23 (constructed): (1 elem) 13 + AttributeTypeAndValue SEQUENCE @50+21 (constructed): (2 elem) 14 + type AttributeType OBJECT_IDENTIFIER @52+10: 0.9.2342.19200300.100.1.25|domainComponent|Men are from Mars, this OID is from Pluto 15 + value AttributeValue [?] IA5String @64+7: example 16 + RelativeDistinguishedName SET @73+19 (constructed): (1 elem) 17 + AttributeTypeAndValue SEQUENCE @75+17 (constructed): (2 elem) 18 + type AttributeType OBJECT_IDENTIFIER @77+3: 2.5.4.3|commonName|X.520 DN component 19 + value AttributeValue [?] PrintableString @82+10: Example CA 20 + thisUpdate utcTime Time UTCTime @94+13: 2005-02-05 12:00:00 UTC 21 + nextUpdate utcTime Time UTCTime @109+13: 2005-02-06 12:00:00 UTC 22 + revokedCertificates SEQUENCE @124+34 (constructed): (1 elem) 23 + SEQUENCE @126+32 (constructed): (3 elem) 24 + userCertificate CertificateSerialNumber INTEGER @128+1: 18 25 + revocationDate utcTime Time UTCTime @131+13: 2004-11-19 15:57:03 UTC 26 + crlEntryExtensions Extensions SEQUENCE @146+12 (constructed): (1 elem) 27 + Extension SEQUENCE @148+10 (constructed): (2 elem) 28 + extnID OBJECT_IDENTIFIER @150+3: 2.5.29.21|cRLReason|X.509 extension 29 + extnValue OCTET_STRING @155+3 (encapsulates): (3 byte)|0A0101 30 + ENUMERATED @157+1: 1 31 + crlExtensions [0] @160+47 (constructed): (1 elem) 32 + Extensions SEQUENCE @162+45 (constructed): (2 elem) 33 + Extension SEQUENCE @164+31 (constructed): (2 elem) 34 + extnID OBJECT_IDENTIFIER @166+3: 2.5.29.35|authorityKeyIdentifier|X.509 extension 35 + extnValue OCTET_STRING @171+24 (encapsulates): (24 byte)|301680140868AF8533C8394A7AF882938E706A4A20842C32 36 + SEQUENCE @173+22 (constructed): (1 elem) 37 + [0] @175+20: (20 byte)|0868AF8533C8394A7AF882938E706A4A20842C32 38 + Extension SEQUENCE @197+10 (constructed): (2 elem) 39 + extnID OBJECT_IDENTIFIER @199+3: 2.5.29.20|cRLNumber|X.509 extension 40 + extnValue OCTET_STRING @204+3 (encapsulates): (3 byte)|02010C 41 + INTEGER @206+1: 12 42 + signatureAlgorithm AlgorithmIdentifier SEQUENCE @209+13 (constructed): (2 elem) 43 + algorithm OBJECT_IDENTIFIER @211+9: 1.2.840.113549.1.1.5|sha1WithRSAEncryption|PKCS #1 44 + parameters ANY NULL @222+0 45 + signature BIT_STRING @224+129: (1024 bit)|0010001011011100000110000111110111110111000010001100111011001100011101011101000011010000011010101001101110101101000100001111010001110110001000111011010010000001011011101011010101101101101111100000111011111011000101010001010001101100110010000001011101101101000111111110111010010000000101111010001001101111011000001110010010111101101010101000110001010101110111101000111010000100011011111001001011111000100111110001000000010010001001111010111101001010110101000010111110000101111000100011011001000100011111011010101010100011010011000010010100111000000101011111111100000000111111010011111001111110111011100011110100100110000100101110101111011000111001110010101101100010111000100010101111000011010001101000000011101111011110001000001011010001000101011100011011010000100111000111001001101010110010111100111001111010111011010110011110011001100010110110111001110000100000010111110101000011010000100111010011000001101001101010111111000001010101010001011110100010001100110100110011010110000001101001100000101011101001001111110000101110
+60
examples/ed25519.cer.dump
··· 1 + Certificate SEQUENCE @0+383 (constructed): (3 elem) 2 + tbsCertificate TBSCertificate SEQUENCE @4+305 (constructed): (8 elem) 3 + version [0] @8+3 (constructed): (1 elem) 4 + Version INTEGER @10+1: 2 5 + serialNumber CertificateSerialNumber INTEGER @13+20: (159 bit)|711090297755414526861352146244170174161660335942 6 + signature AlgorithmIdentifier SEQUENCE @35+5 (constructed): (1 elem) 7 + algorithm OBJECT_IDENTIFIER @37+3: 1.3.101.112|curveEd25519|EdDSA 25519 signature algorithm 8 + issuer rdnSequence Name SEQUENCE @42+53 (constructed): (3 elem) 9 + RelativeDistinguishedName SET @44+11 (constructed): (1 elem) 10 + AttributeTypeAndValue SEQUENCE @46+9 (constructed): (2 elem) 11 + type AttributeType OBJECT_IDENTIFIER @48+3: 2.5.4.6|countryName|X.520 DN component 12 + value AttributeValue [?] PrintableString @53+2: IT 13 + RelativeDistinguishedName SET @57+15 (constructed): (1 elem) 14 + AttributeTypeAndValue SEQUENCE @59+13 (constructed): (2 elem) 15 + type AttributeType OBJECT_IDENTIFIER @61+3: 2.5.4.7|localityName|X.520 DN component 16 + value AttributeValue [?] UTF8String @66+6: Milano 17 + RelativeDistinguishedName SET @74+21 (constructed): (1 elem) 18 + AttributeTypeAndValue SEQUENCE @76+19 (constructed): (2 elem) 19 + type AttributeType OBJECT_IDENTIFIER @78+3: 2.5.4.3|commonName|X.520 DN component 20 + value AttributeValue [?] UTF8String @83+12: Test ed25519 21 + validity Validity SEQUENCE @97+30 (constructed): (2 elem) 22 + notBefore utcTime Time UTCTime @99+13: 2020-09-02 13:25:26 UTC 23 + notAfter utcTime Time UTCTime @114+13: 2030-09-02 13:25:26 UTC 24 + subject rdnSequence Name SEQUENCE @129+53 (constructed): (3 elem) 25 + RelativeDistinguishedName SET @131+11 (constructed): (1 elem) 26 + AttributeTypeAndValue SEQUENCE @133+9 (constructed): (2 elem) 27 + type AttributeType OBJECT_IDENTIFIER @135+3: 2.5.4.6|countryName|X.520 DN component 28 + value AttributeValue [?] PrintableString @140+2: IT 29 + RelativeDistinguishedName SET @144+15 (constructed): (1 elem) 30 + AttributeTypeAndValue SEQUENCE @146+13 (constructed): (2 elem) 31 + type AttributeType OBJECT_IDENTIFIER @148+3: 2.5.4.7|localityName|X.520 DN component 32 + value AttributeValue [?] UTF8String @153+6: Milano 33 + RelativeDistinguishedName SET @161+21 (constructed): (1 elem) 34 + AttributeTypeAndValue SEQUENCE @163+19 (constructed): (2 elem) 35 + type AttributeType OBJECT_IDENTIFIER @165+3: 2.5.4.3|commonName|X.520 DN component 36 + value AttributeValue [?] UTF8String @170+12: Test ed25519 37 + subjectPublicKeyInfo SubjectPublicKeyInfo SEQUENCE @184+42 (constructed): (2 elem) 38 + algorithm AlgorithmIdentifier SEQUENCE @186+5 (constructed): (1 elem) 39 + algorithm OBJECT_IDENTIFIER @188+3: 1.3.101.112|curveEd25519|EdDSA 25519 signature algorithm 40 + subjectPublicKey BIT_STRING @193+33: (256 bit)|0011101110101001001011111111110111001011000101110110011011011110010000001010001010010010111101111001001111011110001100001111100000001010001000111010100000110001001000010101110111010000000001111101100001100011001001000010111011111111011010000010000110000101 41 + extensions [3] @228+83 (constructed): (1 elem) 42 + Extensions SEQUENCE @230+81 (constructed): (3 elem) 43 + Extension SEQUENCE @232+29 (constructed): (2 elem) 44 + extnID OBJECT_IDENTIFIER @234+3: 2.5.29.14|subjectKeyIdentifier|X.509 extension 45 + extnValue OCTET_STRING @239+22 (encapsulates): (22 byte)|04146BA5BDCF9DFA235978126417AE1E72D89A804AE8 46 + OCTET_STRING @241+20: (20 byte)|6BA5BDCF9DFA235978126417AE1E72D89A804AE8 47 + Extension SEQUENCE @263+31 (constructed): (2 elem) 48 + extnID OBJECT_IDENTIFIER @265+3: 2.5.29.35|authorityKeyIdentifier|X.509 extension 49 + extnValue OCTET_STRING @270+24 (encapsulates): (24 byte)|301680146BA5BDCF9DFA235978126417AE1E72D89A804AE8 50 + SEQUENCE @272+22 (constructed): (1 elem) 51 + [0] @274+20: (20 byte)|6BA5BDCF9DFA235978126417AE1E72D89A804AE8 52 + Extension SEQUENCE @296+15 (constructed): (3 elem) 53 + extnID OBJECT_IDENTIFIER @298+3: 2.5.29.19|basicConstraints|X.509 extension 54 + critical BOOLEAN @303+1: true 55 + extnValue OCTET_STRING @306+5 (encapsulates): (5 byte)|30030101FF 56 + SEQUENCE @308+3 (constructed): (1 elem) 57 + BOOLEAN @310+1: true 58 + signatureAlgorithm AlgorithmIdentifier SEQUENCE @313+5 (constructed): (1 elem) 59 + algorithm OBJECT_IDENTIFIER @315+3: 1.3.101.112|curveEd25519|EdDSA 25519 signature algorithm 60 + signature BIT_STRING @320+65: (512 bit)|01101111011100110111011110111110001010001001011001011010001100110011011011010111111001010011010011111101100100001111001111111101010000000111111100011111000000101111100100000000010101111111001000010110000011110001011001101011000001001011111101100101100001001011011010011000110100101101000011010010101111110100110011010110011011110000111010110110111000101110100010011101000001001010001111100000100110010101000011111001110000100110110111011110011100111010110100011101001101010101011110000101011001011000011000000110
+8
examples/ldapmessage.b64
··· 1 + LDAPMessage example as found on ldap.com. 2 + 3 + Original link: 4 + https://ldap.com/ldapv3-wire-protocol-reference-ldap-message/ 5 + 6 + begin-base64 644 ldapmessage.der 7 + MDUCAQVKEWRjPWV4YW1wbGUsZGM9Y29toB0wGwQWMS4yLjg0MC4xMTM1NTYuMS40LjgwNQEB/w== 8 + ====
+7
examples/ldapmessage.b64.dump
··· 1 + LDAPMessage SEQUENCE @0+53 (constructed): (3 elem) 2 + messageID MessageID INTEGER @2+1: 5 3 + protocolOp delRequest CHOICE Application_10 @5+17: (17 byte)|dc=example,dc=com 4 + Controls [?] [0] @24+29 (constructed): (1 elem) 5 + AttributeTypeAndValue SEQUENCE @26+27 (constructed): (2 elem) 6 + type AttributeType [?] OCTET_STRING @28+22: (22 byte)|1.2.840.113556.1.4.805 7 + value AttributeValue [?] BOOLEAN @52+1: true
+10
examples/pkcs1.pem.dump
··· 1 + RSAPrivateKey SEQUENCE @0+605 (constructed): (9 elem) 2 + version Version INTEGER @4+1: 0 3 + modulus INTEGER @7+129: (1024 bit)|117127183230921204401013393277767517103803021018182691416238029726599496957198017684901559383009459523071384847726671610377559004781710040051270748910270447756432733966622455162759462672603884318432883204215291756888413811504344870556870978773843838353155520698675084344179957236491745093327422201227604749459 4 + publicExponent INTEGER @139+3: 65537 5 + privateExponent INTEGER @144+129: (1024 bit)|92276282475226568589241550905865273709561889943250510752753436239739158443231274686159532997597455087892667385718350070754140814118578097684166368734227728473322161416664690885212698653195373932779792506838124961141214987311742627151011567342689730655630521241854903774681567286735997541758916977964830429313 6 + prime1 INTEGER @276+65: (512 bit)|10896821561662485361386011233938116142526936125648167362054539174681694465821232677159478832161550957167298418313068706031799276527005193877616679381489381 7 + prime2 INTEGER @343+65: (512 bit)|10748747473575365133625210720374663113238804836624829882840358384492696273600075746246298849279878235356215808273663889910189484797595139778277124898735639 8 + exponent1 INTEGER @410+64: (511 bit)|6091625365131581796315047890165719534213640521161662994088715561328917102465668272778610952193459304175325574129665657306361751287362700277617869028176853 9 + exponent2 INTEGER @476+65: (512 bit)|9619864112105977791898517014707043200694399482542575521432448550956476604540013165392532656448448632323473488540572223305800601817570919153380021725291669 10 + coefficient INTEGER @543+64: (511 bit)|4162468593383244686217782691133418477400302049612992866028022118893358867845916127581019785866484075341057799618361552573853678007698434146811407259880551
+16
examples/pkcs8-rsa.pem.dump
··· 1 + PrivateKeyInfo SEQUENCE @0+631 (constructed): (3 elem) 2 + version Version INTEGER @4+1: 0 3 + privateKeyAlgorithm AlgorithmIdentifier SEQUENCE @7+13 (constructed): (2 elem) 4 + algorithm OBJECT_IDENTIFIER @9+9: 1.2.840.113549.1.1.1|rsaEncryption|PKCS #1 5 + parameters ANY NULL @20+0 6 + privateKey PrivateKey OCTET_STRING @22+609 (encapsulates): (609 byte)|3082025D02010002818100A6CB6DE27CDF698B92CEE0C4772D4854D2FF8B666BFBF07FA377E47A90571665FD6A5B8C9F2930E4AF28E32E522162AC66CD70AA1B26888E3EEE268A2B59FECA7E4C693AE26B878B3027F5868429FD8BEBE85BFED3B0E5DF0E9D72AAB1216902B074FA2DD59001EFC4CDB1E7305FF48E0D310C0A4F798EFC758F9703C4F96C930203010001028181008367E1BA7E06C57060C8FBEBCCB8B033A3C8105B30D7DC31B2E7D1E97DAE1EC75B4F5FB0F9F3C9C160FE257D68D74495EEA80C0AF838F37C9DB7A24558C21E28C49D57470B002D90A383CAEBB5821A59583D15502F0012C9235F806C62C97F1E3CAFBC72118FCF60743168125801E06CC7293CDE64D241339AAD516E7BCC1081024100D00E8DE65F7C32094B732A5628CEFEDC35ED796B7CEA6297614545DF71D8DBC67EA14565534BFC9BC5F1A680239227189C2D493924A5BD64641169533201D6E5024100CD3AC881CC47AA776A9829C0E529E3D0DBB5A43C366842578341A051DAFAF4F6164F2DC0E72A3BD3B33F8B2F84A6CF35F0781E7C466E677FF8E553DE5C92C6170240744F3E9A83D4AD302F02B1AF3ADF04F0DC20E698E55B2E448C372AA9903E78164E221FE6561B8B9B159C52C51D9D8DC79F3F5DC8D928E268A5DC69F1FD69B3D5024100B7ACEA92B05F5B8370D52A5947400C727A90C0A25B174878C6324FE7B29273F662D50E5FDD04017360B3784058FA69ED1E8082D83AB8C8CCD1D77D0E3FCFE49502404F79B900CE9185833573BBA54E1B1D157EDFE8C37FC328D2520CCE7CC804A9A28B58D937626EBAD5FDE96534BBEE4E292EE8010CFFC8DB1E546C99FC517B4C67 7 + SEQUENCE @26+605 (constructed): (9 elem) 8 + INTEGER @30+1: 0 9 + INTEGER @33+129: (1024 bit)|117127183230921204401013393277767517103803021018182691416238029726599496957198017684901559383009459523071384847726671610377559004781710040051270748910270447756432733966622455162759462672603884318432883204215291756888413811504344870556870978773843838353155520698675084344179957236491745093327422201227604749459 10 + INTEGER @165+3: 65537 11 + INTEGER @170+129: (1024 bit)|92276282475226568589241550905865273709561889943250510752753436239739158443231274686159532997597455087892667385718350070754140814118578097684166368734227728473322161416664690885212698653195373932779792506838124961141214987311742627151011567342689730655630521241854903774681567286735997541758916977964830429313 12 + INTEGER @302+65: (512 bit)|10896821561662485361386011233938116142526936125648167362054539174681694465821232677159478832161550957167298418313068706031799276527005193877616679381489381 13 + INTEGER @369+65: (512 bit)|10748747473575365133625210720374663113238804836624829882840358384492696273600075746246298849279878235356215808273663889910189484797595139778277124898735639 14 + INTEGER @436+64: (511 bit)|6091625365131581796315047890165719534213640521161662994088715561328917102465668272778610952193459304175325574129665657306361751287362700277617869028176853 15 + INTEGER @502+65: (512 bit)|9619864112105977791898517014707043200694399482542575521432448550956476604540013165392532656448448632323473488540572223305800601817570919153380021725291669 16 + INTEGER @569+64: (511 bit)|4162468593383244686217782691133418477400302049612992866028022118893358867845916127581019785866484075341057799618361552573853678007698434146811407259880551
+118
examples/sig-p256-der.p7m.dump
··· 1 + ContentInfo SEQUENCE @0+10868 (constructed): (2 elem) 2 + contentType ContentType OBJECT_IDENTIFIER @4+9: 1.2.840.113549.1.7.2|signedData|PKCS #7 3 + content [0] @15+10853 (constructed): (1 elem) 4 + SignedData SEQUENCE @19+10849 (constructed): (5 elem) 5 + version CMSVersion INTEGER @23+1: 1 6 + digestAlgorithms DigestAlgorithmIdentifiers SET @26+15 (constructed): (1 elem) 7 + DigestAlgorithmIdentifier SEQUENCE @28+13 (constructed): (2 elem) 8 + algorithm OBJECT_IDENTIFIER @30+9: 2.16.840.1.101.3.4.2.1|sha-256|NIST Algorithm 9 + parameters ANY NULL @41+0 10 + encapContentInfo EncapsulatedContentInfo SEQUENCE @43+10053 (constructed): (2 elem) 11 + eContentType ContentType OBJECT_IDENTIFIER @47+9: 1.2.840.113549.1.7.1|data|PKCS #7 12 + eContent [0] @58+10038 (constructed): (1 elem) 13 + OCTET_STRING @62+10034: (10034 byte)|Inizio contenuto.|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|Fine contenuto. 14 + CertificateSet [?] [0] @10100+370 (constructed): (1 elem) 15 + certificate CertificateChoices SEQUENCE @10104+366 (constructed): (3 elem) 16 + tbsCertificate TBSCertificate SEQUENCE @10108+276 (constructed): (8 elem) 17 + version [0] @10112+3 (constructed): (1 elem) 18 + Version INTEGER @10114+1: 2 19 + serialNumber CertificateSerialNumber INTEGER @10117+16: (127 bit)|128087855099855233032551836648087377254 20 + signature AlgorithmIdentifier SEQUENCE @10135+10 (constructed): (1 elem) 21 + algorithm OBJECT_IDENTIFIER @10137+8: 1.2.840.10045.4.3.2|ecdsaWithSHA256|ANSI X9.62 ECDSA algorithm with SHA256 22 + issuer rdnSequence Name SEQUENCE @10147+15 (constructed): (1 elem) 23 + RelativeDistinguishedName SET @10149+13 (constructed): (1 elem) 24 + AttributeTypeAndValue SEQUENCE @10151+11 (constructed): (2 elem) 25 + type AttributeType OBJECT_IDENTIFIER @10153+3: 2.5.4.3|commonName|X.520 DN component 26 + value AttributeValue [?] UTF8String @10158+4: Test 27 + validity Validity SEQUENCE @10164+30 (constructed): (2 elem) 28 + notBefore utcTime Time UTCTime @10166+13: 2018-07-16 14:56:35 UTC 29 + notAfter utcTime Time UTCTime @10181+13: 2019-07-16 14:56:35 UTC 30 + subject rdnSequence Name SEQUENCE @10196+15 (constructed): (1 elem) 31 + RelativeDistinguishedName SET @10198+13 (constructed): (1 elem) 32 + AttributeTypeAndValue SEQUENCE @10200+11 (constructed): (2 elem) 33 + type AttributeType OBJECT_IDENTIFIER @10202+3: 2.5.4.3|commonName|X.520 DN component 34 + value AttributeValue [?] UTF8String @10207+4: Test 35 + subjectPublicKeyInfo SubjectPublicKeyInfo SEQUENCE @10213+89 (constructed): (2 elem) 36 + algorithm AlgorithmIdentifier SEQUENCE @10215+19 (constructed): (2 elem) 37 + algorithm OBJECT_IDENTIFIER @10217+7: 1.2.840.10045.2.1|ecPublicKey|ANSI X9.62 public key type 38 + parameters ANY OBJECT_IDENTIFIER @10226+8: 1.2.840.10045.3.1.7|prime256v1|ANSI X9.62 named elliptic curve 39 + subjectPublicKey BIT_STRING @10236+66: (520 bit)|0000010000100100010011001011011011001100000111000110100100100001111111110100100111011000101111100010011000111110000010110111110011010000010110100010100001100101010110101000010001101100100000100101111011001010111001101110110011100110100110100110101000100001110001001110010011110010001000000010010011000000111010011111010011100100011101001001110010011000101000011010110111110010010111111001000011011110011011101111100101001000001010110110011100011000100000111010011100001110101101001011011110101011100111110000011001000011 40 + extensions [3] @10304+82 (constructed): (1 elem) 41 + Extensions SEQUENCE @10306+80 (constructed): (3 elem) 42 + Extension SEQUENCE @10308+14 (constructed): (3 elem) 43 + extnID OBJECT_IDENTIFIER @10310+3: 2.5.29.15|keyUsage|X.509 extension 44 + critical BOOLEAN @10315+1: true 45 + extnValue OCTET_STRING @10318+4 (encapsulates): (4 byte)|030204F0 46 + BIT_STRING @10320+2: (4 bit)|1111 47 + Extension SEQUENCE @10324+29 (constructed): (2 elem) 48 + extnID OBJECT_IDENTIFIER @10326+3: 2.5.29.14|subjectKeyIdentifier|X.509 extension 49 + extnValue OCTET_STRING @10331+22 (encapsulates): (22 byte)|0414C3C084DF7B040DB038AF518CE397F6EC20D626E6 50 + OCTET_STRING @10333+20: (20 byte)|C3C084DF7B040DB038AF518CE397F6EC20D626E6 51 + Extension SEQUENCE @10355+31 (constructed): (2 elem) 52 + extnID OBJECT_IDENTIFIER @10357+3: 2.5.29.35|authorityKeyIdentifier|X.509 extension 53 + extnValue OCTET_STRING @10362+24 (encapsulates): (24 byte)|30168014C3C084DF7B040DB038AF518CE397F6EC20D626E6 54 + SEQUENCE @10364+22 (constructed): (1 elem) 55 + [0] @10366+20: (20 byte)|C3C084DF7B040DB038AF518CE397F6EC20D626E6 56 + signatureAlgorithm AlgorithmIdentifier SEQUENCE @10388+10 (constructed): (1 elem) 57 + algorithm OBJECT_IDENTIFIER @10390+8: 1.2.840.10045.4.3.2|ecdsaWithSHA256|ANSI X9.62 ECDSA algorithm with SHA256 58 + signature BIT_STRING @10400+72 (encapsulates): (568 bit)|0011000001000101000000100010000100000000110111100110000000011110010101110011110110101111101101011001101111000101010100011101010110001110001111100111101110011110110110100000011000010010110111010000000100010010100000000101101000100010000101111011011100110100011101011001101110001000010001000001011100000010001000000110011111000011111111011110011000000111100000001101010000011100000111010111101000111011100100000010100100011111001111010011100111000100110111000010111100100000011011011100110010111010001011111001100000101100000001101011011001111100000010011011001000110010 59 + SEQUENCE @10403+69 (constructed): (2 elem) 60 + INTEGER @10405+33: (256 bit)|100583279108105959323277080420227859612360091217401498640290749528265835693079 61 + INTEGER @10440+32: (255 bit)|46934510925111877438867701170553238261516280994969183555881415710868278719026 62 + signerInfos SignerInfos SET @10474+394 (constructed): (1 elem) 63 + SignerInfo SEQUENCE @10478+390 (constructed): (6 elem) 64 + version CMSVersion INTEGER @10482+1: 1 65 + sid issuerAndSerialNumber SignerIdentifier SEQUENCE @10485+35 (constructed): (2 elem) 66 + issuer rdnSequence Name SEQUENCE @10487+15 (constructed): (1 elem) 67 + RelativeDistinguishedName SET @10489+13 (constructed): (1 elem) 68 + AttributeTypeAndValue SEQUENCE @10491+11 (constructed): (2 elem) 69 + type AttributeType OBJECT_IDENTIFIER @10493+3: 2.5.4.3|commonName|X.520 DN component 70 + value AttributeValue [?] UTF8String @10498+4: Test 71 + serialNumber CertificateSerialNumber INTEGER @10504+16: (127 bit)|128087855099855233032551836648087377254 72 + digestAlgorithm DigestAlgorithmIdentifier SEQUENCE @10522+13 (constructed): (2 elem) 73 + algorithm OBJECT_IDENTIFIER @10524+9: 2.16.840.1.101.3.4.2.1|sha-256|NIST Algorithm 74 + parameters ANY NULL @10535+0 75 + SignedAttributes [?] [0] @10537+247 (constructed): (5 elem) 76 + Attribute SEQUENCE @10540+24 (constructed): (2 elem) 77 + type AttributeType OBJECT_IDENTIFIER @10542+9: 1.2.840.113549.1.9.3|contentType|PKCS #9 78 + values SET @10553+11 (constructed): (1 elem) 79 + AttributeValue [?] OBJECT_IDENTIFIER @10555+9: 1.2.840.113549.1.7.1|data|PKCS #7 80 + Attribute SEQUENCE @10566+28 (constructed): (2 elem) 81 + type AttributeType OBJECT_IDENTIFIER @10568+9: 1.2.840.113549.1.9.5|signingTime|PKCS #9 82 + values SET @10579+15 (constructed): (1 elem) 83 + AttributeValue [?] UTCTime @10581+13: 2018-07-16 14:56:35 UTC 84 + Attribute SEQUENCE @10596+42 (constructed): (2 elem) 85 + type AttributeType OBJECT_IDENTIFIER @10598+9: 1.2.840.113549.1.9.52|cmsAlgorithmProtection|RFC 6211 86 + values SET @10609+29 (constructed): (1 elem) 87 + AttributeValue [?] SEQUENCE @10611+27 (constructed): (2 elem) 88 + SEQUENCE @10613+13 (constructed): (2 elem) 89 + OBJECT_IDENTIFIER @10615+9: 2.16.840.1.101.3.4.2.1|sha-256|NIST Algorithm 90 + NULL @10626+0 91 + [1] @10628+10 (constructed): (1 elem) 92 + OBJECT_IDENTIFIER @10630+8: 1.2.840.10045.4.3.2|ecdsaWithSHA256|ANSI X9.62 ECDSA algorithm with SHA256 93 + Attribute SEQUENCE @10640+47 (constructed): (2 elem) 94 + type AttributeType OBJECT_IDENTIFIER @10642+9: 1.2.840.113549.1.9.4|messageDigest|PKCS #9 95 + values SET @10653+34 (constructed): (1 elem) 96 + AttributeValue [?] OCTET_STRING @10655+32: (32 byte)|724C51BBE76DA05AFB20CBE8EB037CDAE1AFD713125D2DC13D552DA9F442D24D 97 + Attribute SEQUENCE @10689+96 (constructed): (2 elem) 98 + type AttributeType OBJECT_IDENTIFIER @10691+11: 1.2.840.113549.1.9.16.2.47|signingCertificateV2|S/MIME Authenticated Attributes 99 + values SET @10704+81 (constructed): (1 elem) 100 + AttributeValue [?] SEQUENCE @10706+79 (constructed): (1 elem) 101 + SEQUENCE @10708+77 (constructed): (1 elem) 102 + SEQUENCE @10710+75 (constructed): (2 elem) 103 + OCTET_STRING @10712+32: (32 byte)|BABC08434C58267301E006861D27ECA125670E792797248E76A5717A5BF993C2 104 + SEQUENCE @10746+39 (constructed): (2 elem) 105 + SEQUENCE @10748+19 (constructed): (1 elem) 106 + [4] @10750+17 (constructed): (1 elem) 107 + SEQUENCE @10752+15 (constructed): (1 elem) 108 + SET @10754+13 (constructed): (1 elem) 109 + SEQUENCE @10756+11 (constructed): (2 elem) 110 + OBJECT_IDENTIFIER @10758+3: 2.5.4.3|commonName|X.520 DN component 111 + UTF8String @10763+4: Test 112 + INTEGER @10769+16: (127 bit)|128087855099855233032551836648087377254 113 + signatureAlgorithm SignatureAlgorithmIdentifier SEQUENCE @10787+10 (constructed): (1 elem) 114 + algorithm OBJECT_IDENTIFIER @10789+8: 1.2.840.10045.4.3.2|ecdsaWithSHA256|ANSI X9.62 ECDSA algorithm with SHA256 115 + signature SignatureValue OCTET_STRING @10799+71 (encapsulates): (71 byte)|3045022100F104302EABB428ECC8E71CE2E38F6CBED848A8E9A2B5D5DA19933E485C83CC7102200CBB40A0B7B9B2E048920622FB286FD14695F24CF650BDAA40B885F84C34BBB9 116 + SEQUENCE @10801+69 (constructed): (2 elem) 117 + INTEGER @10803+33: (256 bit)|109014796438891021115527318269695135443977065935278579101750090430030910049393 118 + INTEGER @10838+32: (252 bit)|5758600628818957274240888478952309319266088628943097300803726649607194983353
+5
examples/timestamp-req.b64
··· 1 + RFC3161 TimeStamp Request 2 + 3 + begin-base64 644 timestamp-req.der 4 + ME4CAQEwLzALBglghkgBZQMEAgEEIEbUJK38SA8/2dz78XnG7DJfIYsSer3shYMmZa1VLFIRAhUA 5 + /1AduFa4EwRirIpvChE2VrV/JWYBAf8=
+1 -2
favicon.svg
··· 1 - <?xml version="1.0" encoding="UTF-8"?> 2 - <svg width="192" height="192" version="1.1" viewBox="0 0 50.8 50.8" xmlns="http://www.w3.org/2000/svg"><rect width="50.8" height="50.8" stroke-width=".25275"/><g transform="translate(0 .23698)"><g transform="translate(0 -.30431)"><path transform="matrix(.26458 0 0 .26458 .72192 -3.1337)" d="m65.411 87.986h-31.354l-4.9479 14.167h-20.156l28.802-77.761h23.906l28.802 77.761h-20.156zm-26.354-14.427h21.302l-10.625-30.938zm125.83-46.719v16.458q-6.4063-2.8646-12.5-4.3229t-11.51-1.4583q-7.1875 0-10.625 1.9792t-3.4375 6.1459q0 3.125 2.2917 4.8958 2.3438 1.7188 8.4375 2.9688l8.5417 1.7188q12.969 2.6042 18.438 7.9167 5.4688 5.3125 5.4688 15.104 0 12.865-7.6563 19.167-7.6042 6.25-23.281 6.25-7.3958 0-14.844-1.4062-7.4479-1.4063-14.896-4.1667v-16.927q7.4479 3.9583 14.375 5.9896 6.9792 1.9792 13.438 1.9792 6.5625 0 10.052-2.1875t3.4896-6.25q0-3.6458-2.3958-5.625-2.3438-1.9792-9.4271-3.5417l-7.7604-1.7188q-11.667-2.5-17.083-7.9688-5.3646-5.4688-5.3646-14.74 0-11.615 7.5-17.865 7.5-6.25 21.563-6.25 6.4063 0 13.177 0.98959 6.7708 0.9375 14.01 2.8646z" fill="#58a6ff" aria-label="AS"/><g transform="matrix(.26458 0 0 .26458 2.807 20.959)" style="white-space:pre" aria-label="N1"><path d="m7.2136 24.392h22.396l28.281 53.334v-53.334h19.01v77.761h-22.396l-28.281-53.334v53.334h-19.01z" fill="#58a6ff"/><path d="m109.19 88.298h17.708v-50.261l-18.177 3.75v-13.646l18.073-3.75h19.063v63.906h17.708v13.854h-54.375z" fill="#fffe58"/></g></g></g></svg> 1 + <svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" viewBox="0 0 50.8 50.8"><path d="M0 0h50.8v50.8H0z"/><path fill="#58a6ff" d="M18.028 20.078H9.733l-1.31 3.749H3.092l7.62-20.574h6.325l7.62 20.574h-5.332zm-6.972-3.817h5.636L13.88 8.076zm33.292-12.36v4.354q-1.695-.758-3.308-1.144t-3.045-.386q-1.902 0-2.811.524t-.91 1.626q0 .827.607 1.295.62.455 2.232.786l2.26.454q3.432.69 4.879 2.095t1.446 3.996q0 3.404-2.025 5.072-2.012 1.653-6.16 1.653-1.957 0-3.927-.372t-3.942-1.102v-4.479q1.971 1.047 3.804 1.585 1.846.523 3.555.523 1.737 0 2.66-.578t.923-1.654q0-.965-.634-1.488-.62-.524-2.494-.937l-2.053-.455q-3.087-.661-4.52-2.108-1.42-1.447-1.42-3.9 0-3.073 1.985-4.727 1.984-1.654 5.705-1.654 1.695 0 3.486.262 1.792.248 3.707.758z" aria-label="AS"/><g aria-label="N1" style="white-space:pre"><path fill="#58a6ff" d="M4.716 27.345h5.925l7.483 14.111v-14.11h5.03v20.573h-5.926L9.745 33.81v14.11h-5.03z"/><path fill="#fffe58" d="M31.696 44.254h4.686V30.955l-4.81.993v-3.61l4.782-.993h5.044v16.908h4.685v3.666H31.696z"/></g></svg>
+2 -2
hex.js
··· 1 1 // Hex JavaScript decoder 2 - // Copyright (c) 2008-2024 Lapo Luchini <lapo@lapo.it> 2 + // Copyright (c) 2008 Lapo Luchini <lapo@lapo.it> 3 3 4 4 // Permission to use, copy, modify, and/or distribute this software for any 5 5 // purpose with or without fee is hereby granted, provided that the above 6 6 // copyright notice and this permission notice appear in all copies. 7 - // 7 + // 8 8 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 9 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 10 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-42
index-dark.css
··· 1 - :root { 2 - --main-bg-color: #0d1116; 3 - --main-text-color: #f8f8f2; 4 - --headline-text-color: #8be9fd; 5 - --button-border-color: #505050; 6 - --button-bg-color: #303030; 7 - --button-bghover-color: #404040; 8 - --input-border-color: #505050; 9 - --input-bg-color: #0c0e11; 10 - --link-color: #58a6ff; 11 - --link-hover-color: #9b9bea; 12 - --header-bg-color: #161b22; 13 - --page-bg-color: #000000; 14 - --license-bg-color: #4b4a4a; 15 - --license-border-color: black; 16 - --sub-border-color: #383838; 17 - --preview-bg-color: #989797; 18 - --preview-border-color: #b5b3b3; 19 - --dump-bg-color: #0c0e11; 20 - --dump-border-color: #505050; 21 - } 22 - h1 { 23 - font-weight: 200; 24 - } 25 - .license .hidden { 26 - background-color: #4b4a4a; /*minimal support for IE11*/ 27 - background-color: var(--license-bg-color); 28 - } 29 - .value { 30 - background-color: #303030; /*minimal support for IE11*/ 31 - background-color: var(--button-bg-color); 32 - } 33 - #dump .tag { color: #58a6ff; } 34 - #dump .dlen { color: darkcyan; } 35 - #dump .ulen { color: #00b6b6; } 36 - #dump .intro { color: #58a6ff; } 37 - #dump .outro { color: #00b6b6; } 38 - #dump .skip { color: #707070; background-color: #222222; } 39 - #dump .hexCurrent { background-color: #727272; } 40 - #dump .hexCurrent .hex { background-color: #474747; } 41 - #dump .hexCurrent .tag { color: #6db0fc; } 42 - #dump .hexCurrent .dlen { color: #00b6b6; }
+156 -29
index.css
··· 1 - :root { 1 + html { 2 2 --main-bg-color: #C0C0C0; 3 3 --main-text-color: #000000; 4 4 --headline-text-color: #8be9fd; ··· 18 18 --preview-border-color: #505050; 19 19 --dump-bg-color: #C0C0C0; 20 20 --dump-border-color: #E0E0E0; 21 + --dump-tag: blue; 22 + --dump-dlen: darkcyan; 23 + --dump-ulen: darkgreen; 24 + --dump-intro: blue; 25 + --dump-outro: darkgreen; 26 + --dump-skip: #666666; 27 + --dump-skip-bg: #C0C0C0; 28 + --dump-hex-current: #808080; 29 + --dump-hex-current-hex: #A0A0A0; 30 + --dump-hex-current-dlen: #004040; 31 + --hover-bg-color: #E0E0E0; 32 + --tree-zoom-fix: -1px; 33 + --tree-line: #999; 34 + } 35 + html[data-theme="dark"] { 36 + --main-bg-color: #0d1116; 37 + --main-text-color: #f8f8f2; 38 + --headline-text-color: #8be9fd; 39 + --button-border-color: #505050; 40 + --button-bg-color: #303030; 41 + --button-bghover-color: #404040; 42 + --input-border-color: #505050; 43 + --input-bg-color: #0c0e11; 44 + --link-color: #58a6ff; 45 + --link-hover-color: #9b9bea; 46 + --header-bg-color: #161b22; 47 + --page-bg-color: #000000; 48 + --license-bg-color: #4b4a4a; 49 + --license-border-color: black; 50 + --sub-border-color: #383838; 51 + --preview-bg-color: #989797; 52 + --preview-border-color: #b5b3b3; 53 + --dump-bg-color: #0c0e11; 54 + --dump-border-color: #505050; 55 + --dump-tag: #58a6ff; 56 + --dump-dlen: darkcyan; 57 + --dump-ulen: #00b6b6; 58 + --dump-intro: #58a6ff; 59 + --dump-outro: #00b6b6; 60 + --dump-skip: #707070; 61 + --dump-skip-bg: #222222; 62 + --dump-hex-current: #727272; 63 + --dump-hex-current-hex: #474747; 64 + --dump-hex-current-dlen: #00b6b6; 65 + --hover-bg-color: #505050; 66 + --tree-line: #333; 21 67 } 22 68 html, body { 23 69 background-color: var(--page-bg-color); ··· 83 129 #main-page { 84 130 background-color: var(--main-bg-color); 85 131 border: 0px; 86 - padding: 15px; 132 + padding: 5px; 87 133 } 88 134 #main-page > div { 89 135 position: relative; ··· 115 161 /*display: block;*/ 116 162 visibility: visible; 117 163 } 118 - .node { 119 - position: relative; 120 - } 121 - .sub { 122 - padding-left: 1.5em; 123 - border-left: solid 1px var(--sub-border-color); 124 - } 125 164 .head { 126 165 height: 1em; 127 166 white-space: nowrap; 128 167 } 129 - .head:hover::before { 130 - position: absolute; 131 - content: '-'; 132 - color: red; 133 - border: solid 1px red; 134 - border-radius: 20px; 135 - background-color: black; 136 - /*TODO: use vars instead of hex*/ 137 - } 138 168 .node:hover > .head, .node.hover > .head { 139 169 color: var(--link-color); 140 - font-weight: bold; 170 + background-color: var(--hover-bg-color); 141 171 } 142 172 .node:hover > .head:hover, .node.hover > .head.hover { 143 173 color: var(--link-hover-color); ··· 163 193 position: absolute; 164 194 z-index: 2; 165 195 top: 1.2em; 166 - left: 0; 196 + left: 30px; 167 197 background-color: #efefef; /*minimal support for IE11*/ 168 198 background-color: var(--button-bg-color); 169 199 border: solid 1px var(--button-border-color); ··· 201 231 white-space: pre; 202 232 padding: 5px; 203 233 } 204 - #dump .tag { color: blue; } 205 - #dump .dlen { color: darkcyan; } 206 - #dump .ulen { color: darkgreen; } 207 - #dump .intro { color: blue; } 208 - #dump .outro { color: darkgreen; } 209 - #dump .skip { color: #666666; background-color: #C0C0C0; } 210 - #dump .hexCurrent { background-color: #808080; } 211 - #dump .hexCurrent .hex { background-color: #A0A0A0; } 212 - #dump .hexCurrent .dlen { color: #004040; } 234 + #dump .tag { color: var(--dump-tag); } 235 + #dump .dlen { color: var(--dump-dlen); } 236 + #dump .ulen { color: var(--dump-ulen); } 237 + #dump .intro { color: var(--dump-intro); } 238 + #dump .outro { color: var(--dump-outro); } 239 + #dump .skip { color: var(--dump-skip); background-color: var(--dump-skip-bg); } 240 + #dump .hexCurrent { background-color: var(--dump-hex-current); } 241 + #dump .hexCurrent .hex { background-color: var(--dump-hex-current-hex); } 242 + #dump .hexCurrent .dlen { color: var(--dump-hex-current-dlen); } 213 243 #file { display: none; } 214 244 #area { width: 100%; } 215 245 #contextmenu { ··· 233 263 #contextmenu > button:hover { 234 264 background-color: var(--button-bghover-color); 235 265 } 266 + 267 + .treecollapse { 268 + --spacing: 1.5rem; 269 + --radius: 7px; 270 + padding-inline-start: 0px; 271 + } 272 + .treecollapse li{ 273 + display: block; 274 + position: relative; 275 + padding-left: calc(2 * var(--spacing) - var(--radius) - 2px); 276 + } 277 + .treecollapse ul{ 278 + padding-left: 0; 279 + margin-left: calc(var(--radius) - var(--spacing)); 280 + } 281 + .treecollapse ul li{ 282 + border-left: 1px solid var(--tree-line); 283 + } 284 + .treecollapse ul li:last-child{ 285 + border-color: transparent; 286 + } 287 + .treecollapse ul li::before{ 288 + content: ''; 289 + display: block; 290 + position: absolute; 291 + top: calc(var(--spacing) / -1.6); 292 + left: var(--tree-zoom-fix); 293 + width: calc(var(--spacing) + 2px); 294 + height: calc(var(--spacing) + 1px); 295 + border: solid var(--tree-line); 296 + border-width: 0 0 1px 1px; 297 + } 298 + .treecollapse summary{ 299 + display : block; 300 + cursor : pointer; 301 + } 302 + .treecollapse summary::marker, 303 + .treecollapse summary::-webkit-details-marker{ 304 + display : none; 305 + } 306 + .treecollapse summary:focus{ 307 + outline : none; 308 + } 309 + .treecollapse summary:focus-visible{ 310 + outline : 1px dotted #000; 311 + } 312 + .treecollapse summary::before{ 313 + content: ''; 314 + display: block; 315 + position: absolute; 316 + top: calc(var(--spacing) / 2 - var(--radius)); 317 + left: calc(var(--spacing) - var(--radius) - 1px); 318 + width: calc(2 * var(--radius)); 319 + height: calc(2 * var(--radius)); 320 + } 321 + .treecollapse summary::before{ 322 + z-index: 1; 323 + top: 1px; 324 + background: url('tree-icon-light.svg'); 325 + } 326 + html[data-theme="dark"] .treecollapse summary::before{ 327 + background: url('tree-icon-dark.svg'); 328 + } 329 + .treecollapse details[open] > summary::before{ 330 + background-position : calc(-2 * var(--radius)) 0; 331 + } 332 + 333 + /* 334 + Zoom fix to have straight lines in treeview 335 + Zoom level and dpi resolution: 336 + - 175%: 336dpi 337 + - 150%: 288dpi 338 + - 110%: 212dpi 339 + - 100%: 192dpi 340 + - 90%: 173dpi 341 + - 80%: 154dpi 342 + */ 343 + @media (resolution <= 154dpi) { 344 + :root{ 345 + --tree-zoom-fix: -0.6px; 346 + } 347 + } 348 + @media (155dpi <= resolution < 192dpi) { 349 + :root{ 350 + --tree-zoom-fix: -0.7px; 351 + } 352 + } 353 + @media (192dpi <= resolution < 336dpi) { 354 + :root{ 355 + --tree-zoom-fix: -1px; 356 + } 357 + } 358 + @media (336dpi <= resolution) { 359 + :root{ 360 + --tree-zoom-fix: -0.9px; 361 + } 362 + }
+16 -9
index.html
··· 1 1 <!DOCTYPE html> 2 - <html> 2 + <html data-theme="dark"> 3 3 <head> 4 - <meta charset="US-ASCII"> 4 + <meta charset="UTF-8"> 5 5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 6 + <meta name="theme-color" content="#0d1116" media="(prefers-color-scheme: dark)"> 7 + <meta name="theme-color" content="#C0C0C0" media="(prefers-color-scheme: light)"> 6 8 <title>ASN.1 JavaScript decoder</title> 7 - <link rel="stylesheet" href="index.css" type="text/css" id="theme-base"> 9 + <link rel="stylesheet" href="index.css" type="text/css"> 8 10 <link rel="icon" type="image/svg+xml" sizes="192x192" href="favicon.svg"> 9 11 </head> 10 12 <body> ··· 35 37 <div id="tree"></div> 36 38 </div> 37 39 <form> 38 - <textarea id="area" rows="8"></textarea> 40 + <textarea id="area" rows="8" placeholder="Paste hex or base64 or PEM encoded ASN.1 BER or DER structures here, or load a file."></textarea> 39 41 <br> 40 42 <br> 41 43 <label title="can be slow with big files"><input type="checkbox" id="wantHex" checked="checked"> with hex dump</label> ··· 45 47 <br><br> 46 48 <table> 47 49 <tr><td>Drag or load file:</td><td><input type="file" id="file"></td></tr> 48 - <tr><td>Load examples:</td><td> 50 + <tr id="rowExamples"><td>Load examples:</td><td> 49 51 <select id="examples"> 50 52 <option value="sig-p256-der.p7m">PKCS#7/CMS attached signature (DER)</option> 51 53 <option value="sig-p256-ber.p7m">PKCS#7/CMS attached signature (BER)</option> 52 54 <option value="sig-rsa1024-sha1.p7s">PKCS#7/CMS detached signature (old)</option> 55 + <option value="cms-password.p7m">PKCS#7/CMS encrypted with password</option> 53 56 <option value="letsencrypt-x3.cer">X.509 certificate: Let's Encrypt X3</option> 54 57 <option value="ed25519.cer">X.509 certificate: ed25519 (RFC 8410)</option> 55 58 <option value="pkcs1.pem">PKCS#1 RSA key (RFC 8017)</option> 56 59 <option value="pkcs8-rsa.pem">PKCS#8 RSA key (RFC 5208)</option> 57 60 <option value="pkcs10.pem">PKCS#10 certification request (RFC 2986)</option> 61 + <option value="crl-rfc5280.b64">CRL example (RFC 5280)</option> 58 62 <option value="cmpv2.b64">CMP PKI message (RFC 4210)</option> 63 + <option value="ldapmessage.b64">LDAP message (RFC 4511)</option> 64 + <option value="timestamp-req.b64">TimeStamp request (RFC 3161)</option> 59 65 </select> 60 66 <input id="butExample" type="button" value="load"><br> 61 67 </td></tr> ··· 67 73 <div id="help"> 68 74 <h2>Instructions</h2> 69 75 <p>This page contains a JavaScript generic ASN.1 parser that can decode any valid ASN.1 DER or BER structure whether Base64-encoded (raw base64, PEM armoring and <span class="tt">begin-base64</span> are recognized) or Hex-encoded. </p> 70 - <p>This tool can be used online at the address <a href="https://asn1js.eu/"><span class="tt">https://asn1js.eu/</span></a> or offline, unpacking <a href="https://asn1js.eu/asn1js.zip">the ZIP file</a> in a directory and opening <span class="tt">index.html</span> in a browser</p> 76 + <p>This tool can be used online at the address <a href="https://asn1js.eu/"><span class="tt">https://asn1js.eu/</span></a> or offline, unpacking <a href="https://asn1js.eu/asn1js.zip">the ZIP file</a> in a directory and opening <span class="tt">index-local.html</span> in a browser.</p> 71 77 <p>On the left of the page will be printed a tree representing the hierarchical structure, on the right side an hex dump will be shown. <br> 72 78 Hovering on the tree highlights ancestry (the hovered node and all its ancestors get colored) and the position of the hovered node gets highlighted in the hex dump (with header and content in a different colors). <br> 73 79 Clicking a node in the tree will hide its sub-nodes (collapsed nodes can be noticed because they will become <i>italic</i>).</p> ··· 77 83 <h3>Copyright</h3> 78 84 <div><p class="hidden"> 79 85 ASN.1 JavaScript decoder<br> 80 - Copyright &copy; 2008-2024 Lapo Luchini <a href="mailto:lapo@lapo.it?subject=ASN1js">&lt;lapo@lapo.it&gt;</a><br> 86 + Copyright &copy; 2008-2025 Lapo Luchini <a href="mailto:lapo@lapo.it?subject=ASN1js">&lt;lapo@lapo.it&gt;</a><br> 81 87 <br> 82 88 Permission to use, copy, modify, and/or distribute this software for any 83 89 purpose with or without fee is hereby granted, provided that the above ··· 91 97 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 92 98 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 93 99 </p></div> 94 - <p>ASN.1 JavaScript decoder Copyright &copy; 2008-2024 <a href="https://lapo.it/">Lapo Luchini</a>; released as <a href="https://opensource.org/licenses/isc-license.txt">opensource</a> under the <a href="https://en.wikipedia.org/wiki/ISC_licence">ISC license</a>.</p> 100 + <p>ASN.1 JavaScript decoder Copyright &copy; 2008-2025 <a href="https://lapo.it/">Lapo Luchini</a>; released as <a href="https://opensource.org/licenses/isc-license.txt">opensource</a> under the <a href="https://en.wikipedia.org/wiki/ISC_licence">ISC license</a>.</p> 95 101 </div> 96 102 <p><span class="tt">OBJECT&nbsp;IDENTIFIER</span> values are recognized using data taken from Peter Gutmann's <a href="https://www.cs.auckland.ac.nz/~pgut001/#standards">dumpasn1</a> program.</p> 97 103 <h3>Links</h3> 98 104 <ul> 99 105 <li><a href="https://asn1js.eu/">official website</a></li> 100 106 <li><a href="https://lapo.it/asn1js/">alternate website</a></li> 107 + <li><a href="https://asn1js.eu/index-local.html">single-file version working locally</a> (just save this link)</li> 101 108 <li>previous versions on githack: <select id="tags"><option>[select tag]</option></select></li> 102 109 <li><a href="http://idf.lapo.it/p/asn1js/">InDefero tracker</a> (currently offline)</li> 103 110 <li><a href="https://github.com/lapo-luchini/asn1js">github mirror</a></li> 111 + <li><a href="https://github.com/lapo-luchini/asn1js/blob/trunk/CHANGELOG.md">ChangeLog on GitHub</a></li> 104 112 <li><a href="https://www.openhub.net/p/asn1js">OpenHub code stats</a></li> 105 113 </ul> 106 114 </div> 107 - 108 115 <script type="module" src="index.js"></script> 109 116 </body> 110 117 </html>
+41 -58
index.js
··· 1 + import './theme.js'; 1 2 import { ASN1DOM } from './dom.js'; 2 3 import { Base64 } from './base64.js'; 3 4 import { Hex } from './hex.js'; ··· 15 16 area = id('area'), 16 17 file = id('file'), 17 18 examples = id('examples'), 18 - selectTheme = id('theme-select'), 19 19 selectDefs = id('definitions'), 20 20 selectTag = id('tags'); 21 21 ··· 41 41 function show(asn1) { 42 42 tree.innerHTML = ''; 43 43 dump.innerHTML = ''; 44 - tree.appendChild(asn1.toDOM()); 44 + let ul = document.createElement('ul'); 45 + ul.className = 'treecollapse'; 46 + tree.appendChild(ul); 47 + ul.appendChild(asn1.toDOM()); 45 48 if (wantHex.checked) dump.appendChild(asn1.toHexDOM(undefined, trimHex.checked)); 46 49 } 47 - function decode(der, offset) { 50 + export function decode(der, offset) { 48 51 offset = offset || 0; 49 52 try { 50 53 const asn1 = ASN1DOM.decode(der, offset); ··· 83 86 if (area.value === '') area.value = Base64.pretty(b64); 84 87 try { 85 88 window.location.hash = hash = '#' + b64; 86 - } catch (e) { 89 + } catch (ignore) { 87 90 // fails with "Access Denied" on IE with URLs longer than ~2048 chars 88 91 window.location.hash = hash = '#'; 89 92 } ··· 103 106 text(tree, e); 104 107 } 105 108 } 106 - function decodeText(val) { 109 + export function decodeText(val) { 107 110 try { 108 111 let der = reHex.test(val) ? Hex.decode(val) : Base64.unarmor(val); 109 112 decode(der); ··· 112 115 dump.innerHTML = ''; 113 116 } 114 117 } 115 - function decodeBinaryString(str) { 118 + export function decodeBinaryString(str) { 116 119 let der; 117 120 try { 118 121 if (reHex.test(str)) der = Hex.decode(str); 119 122 else if (Base64.re.test(str)) der = Base64.unarmor(str); 120 123 else der = str; 121 124 decode(der); 122 - } catch (e) { 125 + } catch (ignore) { 123 126 text(tree, 'Cannot decode file.'); 124 127 dump.innerHTML = ''; 125 128 } 126 129 } 127 130 // set up buttons 128 - id('butDecode').onclick = function () { 129 - decodeText(area.value); 131 + const butClickHandlers = { 132 + butDecode: () => { 133 + decodeText(area.value); 134 + }, 135 + butClear: () => { 136 + area.value = ''; 137 + file.value = ''; 138 + tree.innerHTML = ''; 139 + dump.innerHTML = ''; 140 + selectDefs.innerHTML = ''; 141 + hash = window.location.hash = ''; 142 + }, 143 + butExample: () => { 144 + console.log('Loading example:', examples.value); 145 + let request = new XMLHttpRequest(); 146 + request.open('GET', 'examples/' + examples.value, true); 147 + request.onreadystatechange = function () { 148 + if (this.readyState !== 4) return; 149 + if (this.status >= 200 && this.status < 400) { 150 + area.value = this.responseText; 151 + decodeText(this.responseText); 152 + } else { 153 + console.log('Error loading example.'); 154 + } 155 + }; 156 + request.send(); 157 + }, 130 158 }; 131 - id('butClear').onclick = function () { 132 - area.value = ''; 133 - file.value = ''; 134 - tree.innerHTML = ''; 135 - dump.innerHTML = ''; 136 - selectDefs.innerHTML = ''; 137 - hash = window.location.hash = ''; 138 - }; 139 - id('butExample').onclick = function () { 140 - console.log('Loading example:', examples.value); 141 - let request = new XMLHttpRequest(); 142 - request.open('GET', 'examples/' + examples.value, true); 143 - request.onreadystatechange = function () { 144 - if (this.readyState !== 4) return; 145 - if (this.status >= 200 && this.status < 400) { 146 - area.value = this.responseText; 147 - decodeText(this.responseText); 148 - } else { 149 - console.log('Error loading example.'); 150 - } 151 - }; 152 - request.send(); 153 - }; 154 - // set dark theme depending on OS settings 155 - function setTheme() { 156 - let storedTheme = localStorage.getItem('theme'); 157 - let theme = 'os'; 158 - if (storedTheme) 159 - theme = storedTheme; 160 - selectTheme.value = theme; 161 - if (theme == 'os') { 162 - let prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)'); 163 - theme = prefersDarkScheme.matches ? 'dark': 'light'; 164 - } 165 - if (theme == 'dark') { 166 - const css1 = id('theme-base'); 167 - const css2 = css1.cloneNode(); 168 - css2.id = 'theme-override'; 169 - css2.href = 'index-' + theme + '.css'; 170 - css1.parentElement.appendChild(css2); 171 - } else { 172 - const css2 = id('theme-override'); 173 - if (css2) css2.remove(); 174 - } 159 + for (const [name, onClick] of Object.entries(butClickHandlers)) { 160 + let elem = id(name); 161 + if (elem) 162 + elem.onclick = onClick; 175 163 } 176 - setTheme(); 177 - selectTheme.addEventListener('change', function () { 178 - localStorage.setItem('theme', selectTheme.value); 179 - setTheme(); 180 - }); 181 164 // this is only used if window.FileReader 182 165 function read(f) { 183 166 area.value = ''; // clear text area, will get b64 content
-106
int10.js
··· 1 - // Big integer base-10 printing library 2 - // Copyright (c) 2008-2024 Lapo Luchini <lapo@lapo.it> 3 - 4 - // Permission to use, copy, modify, and/or distribute this software for any 5 - // purpose with or without fee is hereby granted, provided that the above 6 - // copyright notice and this permission notice appear in all copies. 7 - // 8 - // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 - // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 - // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 - // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 - // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 - // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 - // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 - 16 - let max = 10000000000000; // biggest 10^n integer that can still fit 2^53 when multiplied by 256 17 - 18 - export class Int10 { 19 - /** 20 - * Arbitrary length base-10 value. 21 - * @param {number} value - Optional initial value (will be 0 otherwise). 22 - */ 23 - constructor(value) { 24 - this.buf = [+value || 0]; 25 - } 26 - 27 - /** 28 - * Multiply value by m and add c. 29 - * @param {number} m - multiplier, must be < =256 30 - * @param {number} c - value to add 31 - */ 32 - mulAdd(m, c) { 33 - // assert(m <= 256) 34 - let b = this.buf, 35 - l = b.length, 36 - i, t; 37 - for (i = 0; i < l; ++i) { 38 - t = b[i] * m + c; 39 - if (t < max) 40 - c = 0; 41 - else { 42 - c = 0|(t / max); 43 - t -= c * max; 44 - } 45 - b[i] = t; 46 - } 47 - if (c > 0) 48 - b[i] = c; 49 - } 50 - 51 - /** 52 - * Subtract value. 53 - * @param {number} c - value to subtract 54 - */ 55 - sub(c) { 56 - let b = this.buf, 57 - l = b.length, 58 - i, t; 59 - for (i = 0; i < l; ++i) { 60 - t = b[i] - c; 61 - if (t < 0) { 62 - t += max; 63 - c = 1; 64 - } else 65 - c = 0; 66 - b[i] = t; 67 - } 68 - while (b[b.length - 1] === 0) 69 - b.pop(); 70 - } 71 - 72 - /** 73 - * Convert to decimal string representation. 74 - * @param {*} base - optional value, only value accepted is 10 75 - */ 76 - toString(base) { 77 - if ((base || 10) != 10) 78 - throw 'only base 10 is supported'; 79 - let b = this.buf, 80 - s = b[b.length - 1].toString(); 81 - for (let i = b.length - 2; i >= 0; --i) 82 - s += (max + b[i]).toString().substring(1); 83 - return s; 84 - } 85 - 86 - /** 87 - * Convert to Number value representation. 88 - * Will probably overflow 2^53 and thus become approximate. 89 - */ 90 - valueOf() { 91 - let b = this.buf, 92 - v = 0; 93 - for (let i = b.length - 1; i >= 0; --i) 94 - v = v * max + b[i]; 95 - return v; 96 - } 97 - 98 - /** 99 - * Return value as a simple Number (if it is <= 10000000000000), or return this. 100 - */ 101 - simplify() { 102 - let b = this.buf; 103 - return (b.length == 1) ? b[0] : this; 104 - } 105 - 106 - }
+47 -66
package.json
··· 1 1 { 2 2 "name": "@lapo/asn1js", 3 - "version": "2.0.1", 3 + "version": "2.1.1", 4 4 "description": "Generic ASN.1 parser/decoder that can decode any valid ASN.1 DER or BER structures.", 5 5 "type": "module", 6 6 "main": "asn1.js", ··· 8 8 "type": "git", 9 9 "url": "git+https://github.com/lapo-luchini/asn1js.git" 10 10 }, 11 - "keywords": [ "asn1", "ber", "der", "pem" ], 11 + "keywords": [ 12 + "asn1", 13 + "ber", 14 + "der", 15 + "pem" 16 + ], 12 17 "author": "Lapo Luchini <lapo@lapo.it>", 13 18 "license": "ISC", 14 - "bugs": { "url": "https://github.com/lapo-luchini/asn1js/issues" }, 19 + "bugs": { 20 + "url": "https://github.com/lapo-luchini/asn1js/issues" 21 + }, 15 22 "homepage": "https://lapo.it/asn1js/", 16 - "files": [ "asn1.js", "base64.js", "hex.js", "int10.js", "oids.js" ], 23 + "files": [ 24 + "asn1.js", 25 + "base64.js", 26 + "hex.js", 27 + "dom.js", 28 + "defs.js", 29 + "oids.js", 30 + "rfcdef.js", 31 + "dumpASN1.js" 32 + ], 17 33 "scripts": { 18 - "lint": "npx eslint asn1.js base64.js hex.js int10.js oids.js tags.js index.js parseRFC.js dumpASN1.js", 34 + "lint": "npx eslint asn1.js base64.js hex.js dom.js defs.js oids.js rfcdef.js tags.js context.js index.js parseRFC.js dumpASN1.js test.js testDefs.js vite.config.js theme.js", 19 35 "lint-action": "npx @action-validator/cli .github/workflows/node.js.yml", 20 - "serve": "echo 'Connect to http://localhost:3000/' ; npx statik --port 3000 .", 21 - "test": "node test" 36 + "build": "vite build", 37 + "serve": "npx -p local-web-server ws", 38 + "test": "node test", 39 + "testdefs": "node testDefs" 40 + }, 41 + "bin": { 42 + "dumpASN1": "./dumpASN1.js" 22 43 }, 23 44 "engines": { 24 - "node": ">=12.20.0" 45 + "node": ">=14.6.0" 25 46 }, 47 + "packageManager": "pnpm@7.33.7", 26 48 "devDependencies": { 27 - "eslint": "^8.34.0" 49 + "@eslint/eslintrc": "^3.3.1", 50 + "@eslint/js": "^9.38.0", 51 + "@rollup/wasm-node": "^4.52.5", 52 + "diff": "^8.0.2", 53 + "eslint": "^9.38.0", 54 + "globals": "^16.4.0", 55 + "htmlparser2": "^9.1.0", 56 + "vite": "^7.1.12", 57 + "vite-plugin-dom": "^1.0.5", 58 + "vite-plugin-singlefile": "^2.3.0" 28 59 }, 29 - "eslintConfig": { 30 - "env": { 31 - "es6": true, 32 - "browser": true, 33 - "node": true 34 - }, 35 - "parserOptions": { 36 - "ecmaVersion": 2015, 37 - "sourceType": "module" 38 - }, 39 - "extends": [ "eslint:recommended" ], 40 - "globals": { 41 - "Uint8Array": "readonly" 42 - }, 43 - "rules": { 44 - "strict": [ "error", "function" ], 45 - "indent": [ "error", 4 ], 46 - "linebreak-style": [ "error", "unix" ], 47 - "semi": [ "warn", "always" ], 48 - "quotes": [ "error", "single", { "avoidEscape": true } ], 49 - "no-var": [ "warn" ], 50 - "comma-dangle": [ "error", "always-multiline" ] 51 - }, 52 - "overrides": [ 53 - { 54 - "files": [ "defs.js" ], 55 - "parserOptions": { 56 - "ecmaVersion": 2020 57 - } 58 - }, { 59 - "files": [ "test.js", "parseRFC.js", "dumpASN1.js" ], 60 - "parserOptions": { 61 - "ecmaVersion": 2021 62 - }, 63 - "rules": { 64 - "strict": [ "error", "global" ] 65 - } 66 - }, { 67 - "files": [ "oids.js" ], 68 - "rules": { 69 - "indent": "off", 70 - "quotes": [ "warn", "double" ] 71 - } 72 - }, { 73 - "files": [ "tags.js", "rfcdef.js" ], 74 - "rules": { 75 - "indent": [ "error", 2, { "ignoredNodes": [ "Program > ExpressionStatement > CallExpression > FunctionExpression > BlockStatement > ExpressionStatement[directive='use strict']:first-child" ] } ], 76 - "comma-dangle": "off", 77 - "quotes": [ "warn", "double" ] 78 - } 79 - }, { 80 - "files": [ "defs.js" ], 81 - "parserOptions": { 82 - "ecmaVersion": 2021 83 - } 84 - } 85 - ] 60 + "overrides": { 61 + "rollup": "npm:@rollup/wasm-node" 62 + }, 63 + "pnpm": { 64 + "overrides": { 65 + "rollup": "npm:@rollup/wasm-node" 66 + } 86 67 } 87 68 }
+66 -14
parseRFC.js
··· 1 1 #! /usr/bin/env node 2 2 3 + // RFC ASN.1 definition parser 4 + // Copyright (c) 2021 Lapo Luchini <lapo@lapo.it> 5 + 6 + // Permission to use, copy, modify, and/or distribute this software for any 7 + // purpose with or without fee is hereby granted, provided that the above 8 + // copyright notice and this permission notice appear in all copies. 9 + // 10 + // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 + // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 + // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 + // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 + // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 + // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 + // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 + 3 18 import * as fs from 'node:fs'; 4 19 5 20 const ··· 47 62 ], 48 63 8017: [ // this RFC uses a lot of currently unsupported syntax 49 64 [ /ALGORITHM-IDENTIFIER ::= CLASS[^-]+--/, '--' ], 50 - [ /\n +\S+ +ALGORITHM-IDENTIFIER[^\n]+(\n [^\n]+)+\n [}]/g, '' ], 51 - [ /AlgorithmIdentifier [{] ALGORITHM-IDENTIFIER:InfoObjectSet [}] ::=(\n [^\n]+)+\n [}]/, 'AlgorithmIdentifier ::= ANY'], 65 + [ /\n +\S+ +ALGORITHM-IDENTIFIER[^\n]+(\n {6}[^\n]+)+\n {3}[}]/g, '' ], 66 + [ /AlgorithmIdentifier [{] ALGORITHM-IDENTIFIER:InfoObjectSet [}] ::=(\n {6}[^\n]+)+\n {3}[}]/, 'AlgorithmIdentifier ::= ANY'], 52 67 [ /algorithm +id-[^,\n]+,/g, 'algorithm ANY,' ], 53 - [ / (sha1 HashAlgorithm|mgf1SHA1 MaskGenAlgorithm|pSpecifiedEmpty PSourceAlgorithm|rSAES-OAEP-Default-Identifier RSAES-AlgorithmIdentifier|rSASSA-PSS-Default-Identifier RSASSA-AlgorithmIdentifier) ::= [{](\n( [^\n]+)?)+\n [}]/g, '' ], 68 + [ / (sha1 {4}HashAlgorithm|mgf1SHA1 {4}MaskGenAlgorithm|pSpecifiedEmpty {4}PSourceAlgorithm|rSAES-OAEP-Default-Identifier {4}RSAES-AlgorithmIdentifier|rSASSA-PSS-Default-Identifier {4}RSASSA-AlgorithmIdentifier) ::= [{](\n( {6}[^\n]+)?)+\n {3}[}]/g, '' ], 54 69 [ / ::= AlgorithmIdentifier [{]\s+[{][^}]+[}]\s+[}]/g, ' ::= AlgorithmIdentifier' ], 55 70 [ /OCTET STRING[(]SIZE[(]0..MAX[)][)]/g, 'OCTET STRING' ], 56 - [ /emptyString EncodingParameters ::= ''H/g, '' ], 71 + [ /emptyString {4}EncodingParameters ::= ''H/g, '' ], 57 72 [ /[(]CONSTRAINED BY[^)]+[)]/g, '' ], 58 73 ], 74 + 4511: [ 75 + [ /^\s+-- .*\r?\n/mg, '' ], // comments 76 + [ 'EXTENSIBILITY IMPLIED', '' ], 77 + [ /\.\.\.(,| {2})/g, '' ], 78 + [ /value AttributeValue/g, 'AttributeValue' ], 79 + [ /control Control/g, 'Control' ], 80 + [ /Attribute ::= PartialAttribute\(WITH COMPONENTS \{[^}]+\}\)/g, 'PartialAttribute ::= SEQUENCE { type AttributeDescription, vals SET SIZE (1..MAX) OF AttributeValue }' ], 81 + [ /,\s+\}/g, '}' ], 82 + [ /SaslCredentials,/g, 'SaslCredentials' ], 83 + [ /(BindResponse|ExtendedResponse) ::= \[APPLICATION [0-9]+\] SEQUENCE \{[^}]+\}/g, '$1 ::= ANY' ], 84 + [ /selector LDAPString/g, 'LDAPString' ], 85 + [ /filter Filter/g, 'Filter' ], 86 + [ /MatchingRuleAssertion,/g, 'MatchingRuleAssertion' ], 87 + [ /OF substring CHOICE/g, 'OF CHOICE' ], 88 + [ /partialAttribute PartialAttribute/g, 'PartialAttribute' ], 89 + [ /uri URI/g, 'URI' ], 90 + [ /OF change SEQUENCE/g, 'OF SEQUENCE' ], 91 + [ /attribute Attribute/g, 'Attribute' ], 92 + ], 59 93 }; 60 94 61 95 // const reWhitespace = /(?:\s|--(?:[}-]?[^\n}-])*(?:\n|--))*/y; ··· 63 97 const reIdentifier = /[a-zA-Z](?:[-]?[a-zA-Z0-9])*/y; 64 98 const reNumber = /0|[1-9][0-9]*/y; 65 99 const reToken = /[(){},[\];]|::=|OPTIONAL|DEFAULT|NULL|TRUE|FALSE|\.\.|OF|SIZE|MIN|MAX|DEFINED BY|DEFINITIONS|TAGS|BEGIN|EXPORTS|IMPORTS|FROM|END/y; 66 - const reType = /ANY|BOOLEAN|INTEGER|(?:BIT|OCTET)\s+STRING|OBJECT\s+IDENTIFIER|SEQUENCE|SET|CHOICE|ENUMERATED|(?:Generalized|UTC)Time|(?:BMP|General|Graphic|IA5|ISO64|Numeric|Printable|Teletex|T61|Universal|UTF8|Videotex|Visible)String/y; 100 + const reType = /ANY|NULL|BOOLEAN|INTEGER|(?:BIT|OCTET)\s+STRING|OBJECT\s+IDENTIFIER|SEQUENCE|SET|CHOICE|ENUMERATED|(?:Generalized|UTC)Time|(?:BMP|General|Graphic|IA5|ISO64|Numeric|Printable|Teletex|T61|Universal|UTF8|Videotex|Visible)String/y; 67 101 const reTagClass = /UNIVERSAL|APPLICATION|PRIVATE|/y; 68 102 const reTagType = /IMPLICIT|EXPLICIT|/y; 69 103 const reTagDefault = /(AUTOMATIC|IMPLICIT|EXPLICIT) TAGS|/y; ··· 179 213 tryToken(expect) { 180 214 let p = this.pos; 181 215 let t; 182 - try { t = this.parseToken(); } catch (e) { /*ignore*/ } 216 + try { t = this.parseToken(); } catch (ignore) { /*ignore*/ } 183 217 // console.log('[debug] tryToken(' + expect + ') = ' + t); 184 218 if (t == expect) 185 219 return true; ··· 224 258 if (this.tryToken('DEFINED BY')) 225 259 x.definedBy = this.parseIdentifier(); 226 260 break; 261 + case 'NULL': 227 262 case 'BOOLEAN': 228 263 case 'OCTET STRING': 229 264 case 'OBJECT IDENTIFIER': ··· 287 322 } 288 323 this.expectToken(')'); 289 324 } 325 + break; 326 + case 'UTCTime': 327 + case 'GeneralizedTime': 290 328 break; 291 329 default: 292 - x.content = 'TODO:unknown'; 330 + x.warning = 'type unknown'; 293 331 } 294 332 } catch (e) { 295 333 console.log('[debug] parseBuiltinType content', e); 296 - x.content = 'TODO:exception'; 334 + x.warning = 'type exception'; 297 335 } 298 336 return x; 299 337 } ··· 305 343 let plicit = this.getRegEx('explicit/implicit', reTagType); 306 344 if (plicit == '') plicit = currentMod.tagDefault; 307 345 let x = this.parseType(); 346 + let name; 347 + switch (tagClass) { // keep in sync with ASN1.typeName 348 + case 'APPLICATION': 349 + name = 'Application ' + t; 350 + break; 351 + case 'PRIVATE': 352 + name = 'Private ' + t; 353 + break; 354 + case 'CONTEXT': 355 + // fall through 356 + default: 357 + name = '[' + t + ']'; 358 + break; 359 + } 308 360 return { 309 - name: '[' + t + ']', 361 + name, 310 362 type: 'tag', 311 363 'class': tagClass, 312 364 explicit: (plicit == 'EXPLICIT'), ··· 319 371 let p = this.pos; 320 372 try { 321 373 return this.parseBuiltinType(); 322 - } catch (e) { 374 + } catch (ignore) { 323 375 // console.log('[debug] parseAssignment failed on parseType', e); 324 376 this.pos = p; 325 377 let x = { ··· 390 442 case 'NULL': 391 443 return null; 392 444 } 393 - } catch (e) { 445 + } catch (ignore) { 394 446 this.pos = p; 395 447 } 396 448 p = this.pos; 397 449 try { 398 450 return this.parseIdentifier(); 399 - } catch (e) { 451 + } catch (ignore) { 400 452 this.pos = p; 401 453 } 402 454 this.exception('Unknown value type.'); ··· 515 567 asn1[currentMod.oid] = currentMod; 516 568 } 517 569 /*asn1 = Object.keys(asn1).sort().reduce( 518 - (obj, key) => { 570 + (obj, key) => { 519 571 obj[key] = asn1[key]; 520 572 return obj; 521 - }, 573 + }, 522 574 {} 523 575 );*/ 524 576 fs.writeFileSync(process.argv[3], JSON.stringify(asn1, null, 2) + '\n', 'utf8');
+1115
pnpm-lock.yaml
··· 1 + lockfileVersion: 5.4 2 + 3 + overrides: 4 + rollup: npm:@rollup/wasm-node 5 + 6 + specifiers: 7 + '@eslint/eslintrc': ^3.3.1 8 + '@eslint/js': ^9.38.0 9 + '@rollup/wasm-node': ^4.52.5 10 + diff: ^8.0.2 11 + eslint: ^9.38.0 12 + globals: ^16.4.0 13 + htmlparser2: ^9.1.0 14 + vite: ^7.1.12 15 + vite-plugin-dom: ^1.0.5 16 + vite-plugin-singlefile: ^2.3.0 17 + 18 + devDependencies: 19 + '@eslint/eslintrc': 3.3.1 20 + '@eslint/js': 9.38.0 21 + '@rollup/wasm-node': 4.52.5 22 + diff: 8.0.2 23 + eslint: 9.38.0 24 + globals: 16.4.0 25 + htmlparser2: 9.1.0 26 + vite: 7.1.12 27 + vite-plugin-dom: 1.0.5_vite@7.1.12 28 + vite-plugin-singlefile: 2.3.0_vite@7.1.12 29 + 30 + packages: 31 + 32 + /@esbuild/aix-ppc64/0.25.11: 33 + resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} 34 + engines: {node: '>=18'} 35 + cpu: [ppc64] 36 + os: [aix] 37 + requiresBuild: true 38 + dev: true 39 + optional: true 40 + 41 + /@esbuild/android-arm/0.25.11: 42 + resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} 43 + engines: {node: '>=18'} 44 + cpu: [arm] 45 + os: [android] 46 + requiresBuild: true 47 + dev: true 48 + optional: true 49 + 50 + /@esbuild/android-arm64/0.25.11: 51 + resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} 52 + engines: {node: '>=18'} 53 + cpu: [arm64] 54 + os: [android] 55 + requiresBuild: true 56 + dev: true 57 + optional: true 58 + 59 + /@esbuild/android-x64/0.25.11: 60 + resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} 61 + engines: {node: '>=18'} 62 + cpu: [x64] 63 + os: [android] 64 + requiresBuild: true 65 + dev: true 66 + optional: true 67 + 68 + /@esbuild/darwin-arm64/0.25.11: 69 + resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} 70 + engines: {node: '>=18'} 71 + cpu: [arm64] 72 + os: [darwin] 73 + requiresBuild: true 74 + dev: true 75 + optional: true 76 + 77 + /@esbuild/darwin-x64/0.25.11: 78 + resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} 79 + engines: {node: '>=18'} 80 + cpu: [x64] 81 + os: [darwin] 82 + requiresBuild: true 83 + dev: true 84 + optional: true 85 + 86 + /@esbuild/freebsd-arm64/0.25.11: 87 + resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} 88 + engines: {node: '>=18'} 89 + cpu: [arm64] 90 + os: [freebsd] 91 + requiresBuild: true 92 + dev: true 93 + optional: true 94 + 95 + /@esbuild/freebsd-x64/0.25.11: 96 + resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} 97 + engines: {node: '>=18'} 98 + cpu: [x64] 99 + os: [freebsd] 100 + requiresBuild: true 101 + dev: true 102 + optional: true 103 + 104 + /@esbuild/linux-arm/0.25.11: 105 + resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} 106 + engines: {node: '>=18'} 107 + cpu: [arm] 108 + os: [linux] 109 + requiresBuild: true 110 + dev: true 111 + optional: true 112 + 113 + /@esbuild/linux-arm64/0.25.11: 114 + resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} 115 + engines: {node: '>=18'} 116 + cpu: [arm64] 117 + os: [linux] 118 + requiresBuild: true 119 + dev: true 120 + optional: true 121 + 122 + /@esbuild/linux-ia32/0.25.11: 123 + resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} 124 + engines: {node: '>=18'} 125 + cpu: [ia32] 126 + os: [linux] 127 + requiresBuild: true 128 + dev: true 129 + optional: true 130 + 131 + /@esbuild/linux-loong64/0.25.11: 132 + resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} 133 + engines: {node: '>=18'} 134 + cpu: [loong64] 135 + os: [linux] 136 + requiresBuild: true 137 + dev: true 138 + optional: true 139 + 140 + /@esbuild/linux-mips64el/0.25.11: 141 + resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} 142 + engines: {node: '>=18'} 143 + cpu: [mips64el] 144 + os: [linux] 145 + requiresBuild: true 146 + dev: true 147 + optional: true 148 + 149 + /@esbuild/linux-ppc64/0.25.11: 150 + resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} 151 + engines: {node: '>=18'} 152 + cpu: [ppc64] 153 + os: [linux] 154 + requiresBuild: true 155 + dev: true 156 + optional: true 157 + 158 + /@esbuild/linux-riscv64/0.25.11: 159 + resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} 160 + engines: {node: '>=18'} 161 + cpu: [riscv64] 162 + os: [linux] 163 + requiresBuild: true 164 + dev: true 165 + optional: true 166 + 167 + /@esbuild/linux-s390x/0.25.11: 168 + resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} 169 + engines: {node: '>=18'} 170 + cpu: [s390x] 171 + os: [linux] 172 + requiresBuild: true 173 + dev: true 174 + optional: true 175 + 176 + /@esbuild/linux-x64/0.25.11: 177 + resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} 178 + engines: {node: '>=18'} 179 + cpu: [x64] 180 + os: [linux] 181 + requiresBuild: true 182 + dev: true 183 + optional: true 184 + 185 + /@esbuild/netbsd-arm64/0.25.11: 186 + resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} 187 + engines: {node: '>=18'} 188 + cpu: [arm64] 189 + os: [netbsd] 190 + requiresBuild: true 191 + dev: true 192 + optional: true 193 + 194 + /@esbuild/netbsd-x64/0.25.11: 195 + resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} 196 + engines: {node: '>=18'} 197 + cpu: [x64] 198 + os: [netbsd] 199 + requiresBuild: true 200 + dev: true 201 + optional: true 202 + 203 + /@esbuild/openbsd-arm64/0.25.11: 204 + resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} 205 + engines: {node: '>=18'} 206 + cpu: [arm64] 207 + os: [openbsd] 208 + requiresBuild: true 209 + dev: true 210 + optional: true 211 + 212 + /@esbuild/openbsd-x64/0.25.11: 213 + resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} 214 + engines: {node: '>=18'} 215 + cpu: [x64] 216 + os: [openbsd] 217 + requiresBuild: true 218 + dev: true 219 + optional: true 220 + 221 + /@esbuild/openharmony-arm64/0.25.11: 222 + resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} 223 + engines: {node: '>=18'} 224 + cpu: [arm64] 225 + os: [openharmony] 226 + requiresBuild: true 227 + dev: true 228 + optional: true 229 + 230 + /@esbuild/sunos-x64/0.25.11: 231 + resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} 232 + engines: {node: '>=18'} 233 + cpu: [x64] 234 + os: [sunos] 235 + requiresBuild: true 236 + dev: true 237 + optional: true 238 + 239 + /@esbuild/win32-arm64/0.25.11: 240 + resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} 241 + engines: {node: '>=18'} 242 + cpu: [arm64] 243 + os: [win32] 244 + requiresBuild: true 245 + dev: true 246 + optional: true 247 + 248 + /@esbuild/win32-ia32/0.25.11: 249 + resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} 250 + engines: {node: '>=18'} 251 + cpu: [ia32] 252 + os: [win32] 253 + requiresBuild: true 254 + dev: true 255 + optional: true 256 + 257 + /@esbuild/win32-x64/0.25.11: 258 + resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} 259 + engines: {node: '>=18'} 260 + cpu: [x64] 261 + os: [win32] 262 + requiresBuild: true 263 + dev: true 264 + optional: true 265 + 266 + /@eslint-community/eslint-utils/4.9.0_eslint@9.38.0: 267 + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} 268 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 269 + peerDependencies: 270 + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 271 + dependencies: 272 + eslint: 9.38.0 273 + eslint-visitor-keys: 3.4.3 274 + dev: true 275 + 276 + /@eslint-community/regexpp/4.12.2: 277 + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} 278 + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 279 + dev: true 280 + 281 + /@eslint/config-array/0.21.1: 282 + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} 283 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 284 + dependencies: 285 + '@eslint/object-schema': 2.1.7 286 + debug: 4.4.3 287 + minimatch: 3.1.2 288 + transitivePeerDependencies: 289 + - supports-color 290 + dev: true 291 + 292 + /@eslint/config-helpers/0.4.2: 293 + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} 294 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 295 + dependencies: 296 + '@eslint/core': 0.17.0 297 + dev: true 298 + 299 + /@eslint/core/0.16.0: 300 + resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==} 301 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 302 + dependencies: 303 + '@types/json-schema': 7.0.15 304 + dev: true 305 + 306 + /@eslint/core/0.17.0: 307 + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} 308 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 309 + dependencies: 310 + '@types/json-schema': 7.0.15 311 + dev: true 312 + 313 + /@eslint/eslintrc/3.3.1: 314 + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} 315 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 316 + dependencies: 317 + ajv: 6.12.6 318 + debug: 4.4.3 319 + espree: 10.4.0 320 + globals: 14.0.0 321 + ignore: 5.3.2 322 + import-fresh: 3.3.1 323 + js-yaml: 4.1.0 324 + minimatch: 3.1.2 325 + strip-json-comments: 3.1.1 326 + transitivePeerDependencies: 327 + - supports-color 328 + dev: true 329 + 330 + /@eslint/js/9.38.0: 331 + resolution: {integrity: sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==} 332 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 333 + dev: true 334 + 335 + /@eslint/object-schema/2.1.7: 336 + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} 337 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 338 + dev: true 339 + 340 + /@eslint/plugin-kit/0.4.1: 341 + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} 342 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 343 + dependencies: 344 + '@eslint/core': 0.17.0 345 + levn: 0.4.1 346 + dev: true 347 + 348 + /@humanfs/core/0.19.1: 349 + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} 350 + engines: {node: '>=18.18.0'} 351 + dev: true 352 + 353 + /@humanfs/node/0.16.7: 354 + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} 355 + engines: {node: '>=18.18.0'} 356 + dependencies: 357 + '@humanfs/core': 0.19.1 358 + '@humanwhocodes/retry': 0.4.3 359 + dev: true 360 + 361 + /@humanwhocodes/module-importer/1.0.1: 362 + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 363 + engines: {node: '>=12.22'} 364 + dev: true 365 + 366 + /@humanwhocodes/retry/0.4.3: 367 + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} 368 + engines: {node: '>=18.18'} 369 + dev: true 370 + 371 + /@rollup/wasm-node/4.52.5: 372 + resolution: {integrity: sha512-ldY4tEzSMBHNwB8TfRpi7RRRjjyfKlwjdebw5pS1lu0xaY3g4RDc6ople2wEYulVOKVeH7ZJwRx0iw4pGtjMHg==} 373 + engines: {node: '>=18.0.0', npm: '>=8.0.0'} 374 + hasBin: true 375 + dependencies: 376 + '@types/estree': 1.0.8 377 + optionalDependencies: 378 + fsevents: 2.3.3 379 + dev: true 380 + 381 + /@types/estree/1.0.8: 382 + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} 383 + dev: true 384 + 385 + /@types/json-schema/7.0.15: 386 + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 387 + dev: true 388 + 389 + /acorn-jsx/5.3.2_acorn@8.15.0: 390 + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 391 + peerDependencies: 392 + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 393 + dependencies: 394 + acorn: 8.15.0 395 + dev: true 396 + 397 + /acorn/8.15.0: 398 + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} 399 + engines: {node: '>=0.4.0'} 400 + hasBin: true 401 + dev: true 402 + 403 + /ajv/6.12.6: 404 + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 405 + dependencies: 406 + fast-deep-equal: 3.1.3 407 + fast-json-stable-stringify: 2.1.0 408 + json-schema-traverse: 0.4.1 409 + uri-js: 4.4.1 410 + dev: true 411 + 412 + /ansi-styles/4.3.0: 413 + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 414 + engines: {node: '>=8'} 415 + dependencies: 416 + color-convert: 2.0.1 417 + dev: true 418 + 419 + /argparse/2.0.1: 420 + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 421 + dev: true 422 + 423 + /balanced-match/1.0.2: 424 + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 425 + dev: true 426 + 427 + /brace-expansion/1.1.12: 428 + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} 429 + dependencies: 430 + balanced-match: 1.0.2 431 + concat-map: 0.0.1 432 + dev: true 433 + 434 + /braces/3.0.3: 435 + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 436 + engines: {node: '>=8'} 437 + dependencies: 438 + fill-range: 7.1.1 439 + dev: true 440 + 441 + /callsites/3.1.0: 442 + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 443 + engines: {node: '>=6'} 444 + dev: true 445 + 446 + /chalk/4.1.2: 447 + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 448 + engines: {node: '>=10'} 449 + dependencies: 450 + ansi-styles: 4.3.0 451 + supports-color: 7.2.0 452 + dev: true 453 + 454 + /color-convert/2.0.1: 455 + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 456 + engines: {node: '>=7.0.0'} 457 + dependencies: 458 + color-name: 1.1.4 459 + dev: true 460 + 461 + /color-name/1.1.4: 462 + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 463 + dev: true 464 + 465 + /concat-map/0.0.1: 466 + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 467 + dev: true 468 + 469 + /cross-spawn/7.0.6: 470 + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 471 + engines: {node: '>= 8'} 472 + dependencies: 473 + path-key: 3.1.1 474 + shebang-command: 2.0.0 475 + which: 2.0.2 476 + dev: true 477 + 478 + /debug/4.4.3: 479 + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} 480 + engines: {node: '>=6.0'} 481 + peerDependencies: 482 + supports-color: '*' 483 + peerDependenciesMeta: 484 + supports-color: 485 + optional: true 486 + dependencies: 487 + ms: 2.1.3 488 + dev: true 489 + 490 + /deep-is/0.1.4: 491 + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 492 + dev: true 493 + 494 + /diff/8.0.2: 495 + resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} 496 + engines: {node: '>=0.3.1'} 497 + dev: true 498 + 499 + /dom-serializer/2.0.0: 500 + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} 501 + dependencies: 502 + domelementtype: 2.3.0 503 + domhandler: 5.0.3 504 + entities: 4.5.0 505 + dev: true 506 + 507 + /domelementtype/2.3.0: 508 + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} 509 + dev: true 510 + 511 + /domhandler/5.0.3: 512 + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} 513 + engines: {node: '>= 4'} 514 + dependencies: 515 + domelementtype: 2.3.0 516 + dev: true 517 + 518 + /domutils/3.2.2: 519 + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} 520 + dependencies: 521 + dom-serializer: 2.0.0 522 + domelementtype: 2.3.0 523 + domhandler: 5.0.3 524 + dev: true 525 + 526 + /entities/4.5.0: 527 + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 528 + engines: {node: '>=0.12'} 529 + dev: true 530 + 531 + /entities/6.0.1: 532 + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} 533 + engines: {node: '>=0.12'} 534 + dev: true 535 + 536 + /esbuild/0.25.11: 537 + resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} 538 + engines: {node: '>=18'} 539 + hasBin: true 540 + requiresBuild: true 541 + optionalDependencies: 542 + '@esbuild/aix-ppc64': 0.25.11 543 + '@esbuild/android-arm': 0.25.11 544 + '@esbuild/android-arm64': 0.25.11 545 + '@esbuild/android-x64': 0.25.11 546 + '@esbuild/darwin-arm64': 0.25.11 547 + '@esbuild/darwin-x64': 0.25.11 548 + '@esbuild/freebsd-arm64': 0.25.11 549 + '@esbuild/freebsd-x64': 0.25.11 550 + '@esbuild/linux-arm': 0.25.11 551 + '@esbuild/linux-arm64': 0.25.11 552 + '@esbuild/linux-ia32': 0.25.11 553 + '@esbuild/linux-loong64': 0.25.11 554 + '@esbuild/linux-mips64el': 0.25.11 555 + '@esbuild/linux-ppc64': 0.25.11 556 + '@esbuild/linux-riscv64': 0.25.11 557 + '@esbuild/linux-s390x': 0.25.11 558 + '@esbuild/linux-x64': 0.25.11 559 + '@esbuild/netbsd-arm64': 0.25.11 560 + '@esbuild/netbsd-x64': 0.25.11 561 + '@esbuild/openbsd-arm64': 0.25.11 562 + '@esbuild/openbsd-x64': 0.25.11 563 + '@esbuild/openharmony-arm64': 0.25.11 564 + '@esbuild/sunos-x64': 0.25.11 565 + '@esbuild/win32-arm64': 0.25.11 566 + '@esbuild/win32-ia32': 0.25.11 567 + '@esbuild/win32-x64': 0.25.11 568 + dev: true 569 + 570 + /escape-string-regexp/4.0.0: 571 + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 572 + engines: {node: '>=10'} 573 + dev: true 574 + 575 + /eslint-scope/8.4.0: 576 + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} 577 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 578 + dependencies: 579 + esrecurse: 4.3.0 580 + estraverse: 5.3.0 581 + dev: true 582 + 583 + /eslint-visitor-keys/3.4.3: 584 + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 585 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 586 + dev: true 587 + 588 + /eslint-visitor-keys/4.2.1: 589 + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} 590 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 591 + dev: true 592 + 593 + /eslint/9.38.0: 594 + resolution: {integrity: sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==} 595 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 596 + hasBin: true 597 + peerDependencies: 598 + jiti: '*' 599 + peerDependenciesMeta: 600 + jiti: 601 + optional: true 602 + dependencies: 603 + '@eslint-community/eslint-utils': 4.9.0_eslint@9.38.0 604 + '@eslint-community/regexpp': 4.12.2 605 + '@eslint/config-array': 0.21.1 606 + '@eslint/config-helpers': 0.4.2 607 + '@eslint/core': 0.16.0 608 + '@eslint/eslintrc': 3.3.1 609 + '@eslint/js': 9.38.0 610 + '@eslint/plugin-kit': 0.4.1 611 + '@humanfs/node': 0.16.7 612 + '@humanwhocodes/module-importer': 1.0.1 613 + '@humanwhocodes/retry': 0.4.3 614 + '@types/estree': 1.0.8 615 + ajv: 6.12.6 616 + chalk: 4.1.2 617 + cross-spawn: 7.0.6 618 + debug: 4.4.3 619 + escape-string-regexp: 4.0.0 620 + eslint-scope: 8.4.0 621 + eslint-visitor-keys: 4.2.1 622 + espree: 10.4.0 623 + esquery: 1.6.0 624 + esutils: 2.0.3 625 + fast-deep-equal: 3.1.3 626 + file-entry-cache: 8.0.0 627 + find-up: 5.0.0 628 + glob-parent: 6.0.2 629 + ignore: 5.3.2 630 + imurmurhash: 0.1.4 631 + is-glob: 4.0.3 632 + json-stable-stringify-without-jsonify: 1.0.1 633 + lodash.merge: 4.6.2 634 + minimatch: 3.1.2 635 + natural-compare: 1.4.0 636 + optionator: 0.9.4 637 + transitivePeerDependencies: 638 + - supports-color 639 + dev: true 640 + 641 + /espree/10.4.0: 642 + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} 643 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 644 + dependencies: 645 + acorn: 8.15.0 646 + acorn-jsx: 5.3.2_acorn@8.15.0 647 + eslint-visitor-keys: 4.2.1 648 + dev: true 649 + 650 + /esquery/1.6.0: 651 + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} 652 + engines: {node: '>=0.10'} 653 + dependencies: 654 + estraverse: 5.3.0 655 + dev: true 656 + 657 + /esrecurse/4.3.0: 658 + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 659 + engines: {node: '>=4.0'} 660 + dependencies: 661 + estraverse: 5.3.0 662 + dev: true 663 + 664 + /estraverse/5.3.0: 665 + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 666 + engines: {node: '>=4.0'} 667 + dev: true 668 + 669 + /esutils/2.0.3: 670 + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 671 + engines: {node: '>=0.10.0'} 672 + dev: true 673 + 674 + /fast-deep-equal/3.1.3: 675 + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 676 + dev: true 677 + 678 + /fast-json-stable-stringify/2.1.0: 679 + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 680 + dev: true 681 + 682 + /fast-levenshtein/2.0.6: 683 + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 684 + dev: true 685 + 686 + /fdir/6.5.0_picomatch@4.0.3: 687 + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} 688 + engines: {node: '>=12.0.0'} 689 + peerDependencies: 690 + picomatch: ^3 || ^4 691 + peerDependenciesMeta: 692 + picomatch: 693 + optional: true 694 + dependencies: 695 + picomatch: 4.0.3 696 + dev: true 697 + 698 + /file-entry-cache/8.0.0: 699 + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 700 + engines: {node: '>=16.0.0'} 701 + dependencies: 702 + flat-cache: 4.0.1 703 + dev: true 704 + 705 + /fill-range/7.1.1: 706 + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 707 + engines: {node: '>=8'} 708 + dependencies: 709 + to-regex-range: 5.0.1 710 + dev: true 711 + 712 + /find-up/5.0.0: 713 + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 714 + engines: {node: '>=10'} 715 + dependencies: 716 + locate-path: 6.0.0 717 + path-exists: 4.0.0 718 + dev: true 719 + 720 + /flat-cache/4.0.1: 721 + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} 722 + engines: {node: '>=16'} 723 + dependencies: 724 + flatted: 3.3.3 725 + keyv: 4.5.4 726 + dev: true 727 + 728 + /flatted/3.3.3: 729 + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} 730 + dev: true 731 + 732 + /fsevents/2.3.3: 733 + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 734 + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 735 + os: [darwin] 736 + requiresBuild: true 737 + dev: true 738 + optional: true 739 + 740 + /glob-parent/6.0.2: 741 + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 742 + engines: {node: '>=10.13.0'} 743 + dependencies: 744 + is-glob: 4.0.3 745 + dev: true 746 + 747 + /globals/14.0.0: 748 + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} 749 + engines: {node: '>=18'} 750 + dev: true 751 + 752 + /globals/16.4.0: 753 + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} 754 + engines: {node: '>=18'} 755 + dev: true 756 + 757 + /has-flag/4.0.0: 758 + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 759 + engines: {node: '>=8'} 760 + dev: true 761 + 762 + /htmlparser2/10.0.0: 763 + resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} 764 + dependencies: 765 + domelementtype: 2.3.0 766 + domhandler: 5.0.3 767 + domutils: 3.2.2 768 + entities: 6.0.1 769 + dev: true 770 + 771 + /htmlparser2/9.1.0: 772 + resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} 773 + dependencies: 774 + domelementtype: 2.3.0 775 + domhandler: 5.0.3 776 + domutils: 3.2.2 777 + entities: 4.5.0 778 + dev: true 779 + 780 + /ignore/5.3.2: 781 + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 782 + engines: {node: '>= 4'} 783 + dev: true 784 + 785 + /import-fresh/3.3.1: 786 + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} 787 + engines: {node: '>=6'} 788 + dependencies: 789 + parent-module: 1.0.1 790 + resolve-from: 4.0.0 791 + dev: true 792 + 793 + /imurmurhash/0.1.4: 794 + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 795 + engines: {node: '>=0.8.19'} 796 + dev: true 797 + 798 + /is-extglob/2.1.1: 799 + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 800 + engines: {node: '>=0.10.0'} 801 + dev: true 802 + 803 + /is-glob/4.0.3: 804 + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 805 + engines: {node: '>=0.10.0'} 806 + dependencies: 807 + is-extglob: 2.1.1 808 + dev: true 809 + 810 + /is-number/7.0.0: 811 + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 812 + engines: {node: '>=0.12.0'} 813 + dev: true 814 + 815 + /isexe/2.0.0: 816 + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 817 + dev: true 818 + 819 + /js-yaml/4.1.0: 820 + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 821 + hasBin: true 822 + dependencies: 823 + argparse: 2.0.1 824 + dev: true 825 + 826 + /json-buffer/3.0.1: 827 + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 828 + dev: true 829 + 830 + /json-schema-traverse/0.4.1: 831 + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 832 + dev: true 833 + 834 + /json-stable-stringify-without-jsonify/1.0.1: 835 + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 836 + dev: true 837 + 838 + /keyv/4.5.4: 839 + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 840 + dependencies: 841 + json-buffer: 3.0.1 842 + dev: true 843 + 844 + /levn/0.4.1: 845 + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 846 + engines: {node: '>= 0.8.0'} 847 + dependencies: 848 + prelude-ls: 1.2.1 849 + type-check: 0.4.0 850 + dev: true 851 + 852 + /locate-path/6.0.0: 853 + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 854 + engines: {node: '>=10'} 855 + dependencies: 856 + p-locate: 5.0.0 857 + dev: true 858 + 859 + /lodash.merge/4.6.2: 860 + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 861 + dev: true 862 + 863 + /micromatch/4.0.8: 864 + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 865 + engines: {node: '>=8.6'} 866 + dependencies: 867 + braces: 3.0.3 868 + picomatch: 2.3.1 869 + dev: true 870 + 871 + /minimatch/3.1.2: 872 + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 873 + dependencies: 874 + brace-expansion: 1.1.12 875 + dev: true 876 + 877 + /ms/2.1.3: 878 + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 879 + dev: true 880 + 881 + /nanoid/3.3.11: 882 + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 883 + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 884 + hasBin: true 885 + dev: true 886 + 887 + /natural-compare/1.4.0: 888 + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 889 + dev: true 890 + 891 + /optionator/0.9.4: 892 + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} 893 + engines: {node: '>= 0.8.0'} 894 + dependencies: 895 + deep-is: 0.1.4 896 + fast-levenshtein: 2.0.6 897 + levn: 0.4.1 898 + prelude-ls: 1.2.1 899 + type-check: 0.4.0 900 + word-wrap: 1.2.5 901 + dev: true 902 + 903 + /p-limit/3.1.0: 904 + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 905 + engines: {node: '>=10'} 906 + dependencies: 907 + yocto-queue: 0.1.0 908 + dev: true 909 + 910 + /p-locate/5.0.0: 911 + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 912 + engines: {node: '>=10'} 913 + dependencies: 914 + p-limit: 3.1.0 915 + dev: true 916 + 917 + /parent-module/1.0.1: 918 + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 919 + engines: {node: '>=6'} 920 + dependencies: 921 + callsites: 3.1.0 922 + dev: true 923 + 924 + /path-exists/4.0.0: 925 + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 926 + engines: {node: '>=8'} 927 + dev: true 928 + 929 + /path-key/3.1.1: 930 + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 931 + engines: {node: '>=8'} 932 + dev: true 933 + 934 + /picocolors/1.1.1: 935 + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 936 + dev: true 937 + 938 + /picomatch/2.3.1: 939 + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 940 + engines: {node: '>=8.6'} 941 + dev: true 942 + 943 + /picomatch/4.0.3: 944 + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} 945 + engines: {node: '>=12'} 946 + dev: true 947 + 948 + /postcss/8.5.6: 949 + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} 950 + engines: {node: ^10 || ^12 || >=14} 951 + dependencies: 952 + nanoid: 3.3.11 953 + picocolors: 1.1.1 954 + source-map-js: 1.2.1 955 + dev: true 956 + 957 + /prelude-ls/1.2.1: 958 + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 959 + engines: {node: '>= 0.8.0'} 960 + dev: true 961 + 962 + /punycode/2.3.1: 963 + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 964 + engines: {node: '>=6'} 965 + dev: true 966 + 967 + /resolve-from/4.0.0: 968 + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 969 + engines: {node: '>=4'} 970 + dev: true 971 + 972 + /shebang-command/2.0.0: 973 + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 974 + engines: {node: '>=8'} 975 + dependencies: 976 + shebang-regex: 3.0.0 977 + dev: true 978 + 979 + /shebang-regex/3.0.0: 980 + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 981 + engines: {node: '>=8'} 982 + dev: true 983 + 984 + /source-map-js/1.2.1: 985 + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 986 + engines: {node: '>=0.10.0'} 987 + dev: true 988 + 989 + /strip-json-comments/3.1.1: 990 + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 991 + engines: {node: '>=8'} 992 + dev: true 993 + 994 + /supports-color/7.2.0: 995 + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 996 + engines: {node: '>=8'} 997 + dependencies: 998 + has-flag: 4.0.0 999 + dev: true 1000 + 1001 + /tinyglobby/0.2.15: 1002 + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} 1003 + engines: {node: '>=12.0.0'} 1004 + dependencies: 1005 + fdir: 6.5.0_picomatch@4.0.3 1006 + picomatch: 4.0.3 1007 + dev: true 1008 + 1009 + /to-regex-range/5.0.1: 1010 + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1011 + engines: {node: '>=8.0'} 1012 + dependencies: 1013 + is-number: 7.0.0 1014 + dev: true 1015 + 1016 + /type-check/0.4.0: 1017 + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1018 + engines: {node: '>= 0.8.0'} 1019 + dependencies: 1020 + prelude-ls: 1.2.1 1021 + dev: true 1022 + 1023 + /uri-js/4.4.1: 1024 + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1025 + dependencies: 1026 + punycode: 2.3.1 1027 + dev: true 1028 + 1029 + /vite-plugin-dom/1.0.5_vite@7.1.12: 1030 + resolution: {integrity: sha512-G3MbuH30FpBD800I26xlB6lUiDm7sCxvQkHPt9OAJyUEbyiO9UWrKADxVUhWbO65WqL/TGtH1OEez+w++TlfMw==} 1031 + peerDependencies: 1032 + vite: '>=4.0.0' 1033 + dependencies: 1034 + htmlparser2: 10.0.0 1035 + vite: 7.1.12 1036 + dev: true 1037 + 1038 + /vite-plugin-singlefile/2.3.0_vite@7.1.12: 1039 + resolution: {integrity: sha512-DAcHzYypM0CasNLSz/WG0VdKOCxGHErfrjOoyIPiNxTPTGmO6rRD/te93n1YL/s+miXq66ipF1brMBikf99c6A==} 1040 + engines: {node: '>18.0.0'} 1041 + peerDependencies: 1042 + rollup: ^4.44.1 1043 + vite: ^5.4.11 || ^6.0.0 || ^7.0.0 1044 + dependencies: 1045 + micromatch: 4.0.8 1046 + vite: 7.1.12 1047 + dev: true 1048 + 1049 + /vite/7.1.12: 1050 + resolution: {integrity: sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==} 1051 + engines: {node: ^20.19.0 || >=22.12.0} 1052 + hasBin: true 1053 + peerDependencies: 1054 + '@types/node': ^20.19.0 || >=22.12.0 1055 + jiti: '>=1.21.0' 1056 + less: ^4.0.0 1057 + lightningcss: ^1.21.0 1058 + sass: ^1.70.0 1059 + sass-embedded: ^1.70.0 1060 + stylus: '>=0.54.8' 1061 + sugarss: ^5.0.0 1062 + terser: ^5.16.0 1063 + tsx: ^4.8.1 1064 + yaml: ^2.4.2 1065 + peerDependenciesMeta: 1066 + '@types/node': 1067 + optional: true 1068 + jiti: 1069 + optional: true 1070 + less: 1071 + optional: true 1072 + lightningcss: 1073 + optional: true 1074 + sass: 1075 + optional: true 1076 + sass-embedded: 1077 + optional: true 1078 + stylus: 1079 + optional: true 1080 + sugarss: 1081 + optional: true 1082 + terser: 1083 + optional: true 1084 + tsx: 1085 + optional: true 1086 + yaml: 1087 + optional: true 1088 + dependencies: 1089 + esbuild: 0.25.11 1090 + fdir: 6.5.0_picomatch@4.0.3 1091 + picomatch: 4.0.3 1092 + postcss: 8.5.6 1093 + rollup: /@rollup/wasm-node/4.52.5 1094 + tinyglobby: 0.2.15 1095 + optionalDependencies: 1096 + fsevents: 2.3.3 1097 + dev: true 1098 + 1099 + /which/2.0.2: 1100 + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1101 + engines: {node: '>= 8'} 1102 + hasBin: true 1103 + dependencies: 1104 + isexe: 2.0.0 1105 + dev: true 1106 + 1107 + /word-wrap/1.2.5: 1108 + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} 1109 + engines: {node: '>=0.10.0'} 1110 + dev: true 1111 + 1112 + /yocto-queue/0.1.0: 1113 + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1114 + engines: {node: '>=10'} 1115 + dev: true
+9 -5
release.sh
··· 1 1 #!/bin/sh 2 2 set -e 3 3 FILES=" 4 - asn1.js oids.js defs.js base64.js hex.js int10.js dom.js rfcdef.js test.js tags.js 5 - index.css index-dark.css index.js index.html favicon.svg 6 - README.md LICENSE 4 + asn1.js oids.js defs.js base64.js hex.js dom.js context.js theme.js 5 + rfcdef.js test.js tags.js 6 + index.html index.css index.js index-local.html 7 + favicon.svg tree-icon-light.svg tree-icon-dark.svg 8 + README.md LICENSE CHANGELOG.md 7 9 updateOID.sh check.sh 8 10 examples 9 11 " ··· 25 27 END { print "};" } 26 28 ' > tags.js 27 29 chmod 644 examples/* 28 - type gsha256sum >/dev/null && SHA256=gsha256sum || SHA256=sha256sum 29 - $SHA256 -t $FILES | gpg --clearsign > sha256sums.asc 30 + type gsha256sum >/dev/null 2>/dev/null && SHA256=gsha256sum || SHA256=sha256sum 31 + pnpm build 32 + cp dist/index.html index-local.html 33 + $SHA256 -t $FILES examples/* | gpg --clearsign > sha256sums.asc 30 34 7z a -tzip -mx=9 asn1js.zip $FILES sha256sums.asc 31 35 rsync -Pvrtz asn1js.zip $FILES lapo.it:www/asn1js/
+1517 -30
rfcdef.js
··· 1 - // content parsed from ASN.1 definitions as found in the following RFCs: 5280 5208 3369 3161 2986 4211 4210 8017 1 + // content parsed from ASN.1 definitions as found in the following RFCs: 5280 5208 3369 3161 2986 4211 4210 8017 4511 2 2 // Copyright (C) The IETF Trust (2008) 3 3 // as far as I can tell this file is allowed under the following clause: 4 4 // It is acceptable under the current IETF rules (RFC 5378) to modify extracted code if necessary. ··· 1606 1606 { 1607 1607 "id": "utcTime", 1608 1608 "name": "UTCTime", 1609 - "type": "builtin", 1610 - "content": "TODO:unknown" 1609 + "type": "builtin" 1611 1610 }, 1612 1611 { 1613 1612 "id": "generalTime", 1614 1613 "name": "GeneralizedTime", 1615 - "type": "builtin", 1616 - "content": "TODO:unknown" 1614 + "type": "builtin" 1617 1615 } 1618 1616 ] 1619 1617 } ··· 1985 1983 "CountryName": { 1986 1984 "name": "CountryName", 1987 1985 "type": { 1988 - "name": "[1]", 1986 + "name": "Application 1", 1989 1987 "type": "tag", 1990 1988 "class": "APPLICATION", 1991 1989 "explicit": true, ··· 2017 2015 "AdministrationDomainName": { 2018 2016 "name": "AdministrationDomainName", 2019 2017 "type": { 2020 - "name": "[2]", 2018 + "name": "Application 2", 2021 2019 "type": "tag", 2022 2020 "class": "APPLICATION", 2023 2021 "explicit": true, ··· 3382 3380 "name": "", 3383 3381 "type": { 3384 3382 "name": "GeneralizedTime", 3385 - "type": "builtin", 3386 - "content": "TODO:unknown" 3383 + "type": "builtin" 3387 3384 } 3388 3385 } 3389 3386 ], ··· 3400 3397 "name": "", 3401 3398 "type": { 3402 3399 "name": "GeneralizedTime", 3403 - "type": "builtin", 3404 - "content": "TODO:unknown" 3400 + "type": "builtin" 3405 3401 } 3406 3402 } 3407 3403 ], ··· 4494 4490 "name": "InvalidityDate", 4495 4491 "type": { 4496 4492 "name": "GeneralizedTime", 4497 - "type": "builtin", 4498 - "content": "TODO:unknown" 4493 + "type": "builtin" 4499 4494 } 4500 4495 } 4501 4496 } ··· 5566 5561 "id": "date", 5567 5562 "name": "GeneralizedTime", 5568 5563 "type": "builtin", 5569 - "content": "TODO:unknown", 5570 5564 "optional": true 5571 5565 }, 5572 5566 { ··· 5629 5623 "id": "date", 5630 5624 "name": "GeneralizedTime", 5631 5625 "type": "builtin", 5632 - "content": "TODO:unknown", 5633 5626 "optional": true 5634 5627 }, 5635 5628 { ··· 6142 6135 { 6143 6136 "id": "utcTime", 6144 6137 "name": "UTCTime", 6145 - "type": "builtin", 6146 - "content": "TODO:unknown" 6138 + "type": "builtin" 6147 6139 }, 6148 6140 { 6149 6141 "id": "generalTime", 6150 6142 "name": "GeneralizedTime", 6151 - "type": "builtin", 6152 - "content": "TODO:unknown" 6143 + "type": "builtin" 6153 6144 } 6154 6145 ] 6155 6146 } ··· 6664 6655 { 6665 6656 "id": "genTime", 6666 6657 "name": "GeneralizedTime", 6667 - "type": "builtin", 6668 - "content": "TODO:unknown" 6658 + "type": "builtin" 6669 6659 }, 6670 6660 { 6671 6661 "id": "accuracy", ··· 7464 7454 "name": "", 7465 7455 "type": { 7466 7456 "name": "NULL", 7467 - "type": "defined" 7457 + "type": "builtin" 7468 7458 } 7469 7459 } 7470 7460 ] ··· 8345 8335 "name": "", 8346 8336 "type": { 8347 8337 "name": "GeneralizedTime", 8348 - "type": "builtin", 8349 - "content": "TODO:unknown" 8338 + "type": "builtin" 8350 8339 } 8351 8340 } 8352 8341 ], ··· 9649 9638 { 9650 9639 "id": "willBeRevokedAt", 9651 9640 "name": "GeneralizedTime", 9652 - "type": "builtin", 9653 - "content": "TODO:unknown" 9641 + "type": "builtin" 9654 9642 }, 9655 9643 { 9656 9644 "id": "badSinceDate", 9657 9645 "name": "GeneralizedTime", 9658 - "type": "builtin", 9659 - "content": "TODO:unknown" 9646 + "type": "builtin" 9660 9647 }, 9661 9648 { 9662 9649 "id": "crlDetails", ··· 9724 9711 "name": "PKIConfirmContent", 9725 9712 "type": { 9726 9713 "name": "NULL", 9727 - "type": "defined" 9714 + "type": "builtin" 9728 9715 } 9729 9716 }, 9730 9717 "InfoTypeAndValue": { ··· 10041 10028 "name": "SHA1Parameters", 10042 10029 "type": { 10043 10030 "name": "NULL", 10044 - "type": "defined" 10031 + "type": "builtin" 10045 10032 } 10046 10033 }, 10047 10034 "MaskGenAlgorithm": { ··· 10382 10369 "type": { 10383 10370 "name": "AlgorithmIdentifier", 10384 10371 "type": "defined" 10372 + } 10373 + } 10374 + } 10375 + }, 10376 + "1.3.6.1.1.18": { 10377 + "name": "Lightweight-Directory-Access-Protocol-V3", 10378 + "oid": "1.3.6.1.1.18", 10379 + "source": "rfc4511.txt", 10380 + "tagDefault": "IMPLICIT", 10381 + "values": { 10382 + "maxInt": { 10383 + "name": "maxInt", 10384 + "type": { 10385 + "name": "INTEGER", 10386 + "type": "builtin" 10387 + }, 10388 + "value": 2147483647 10389 + } 10390 + }, 10391 + "types": { 10392 + "LDAPMessage": { 10393 + "name": "LDAPMessage", 10394 + "type": { 10395 + "name": "SEQUENCE", 10396 + "type": "builtin", 10397 + "content": [ 10398 + { 10399 + "id": "messageID", 10400 + "name": "MessageID", 10401 + "type": "defined" 10402 + }, 10403 + { 10404 + "id": "protocolOp", 10405 + "name": "CHOICE", 10406 + "type": "builtin", 10407 + "content": [ 10408 + { 10409 + "id": "bindRequest", 10410 + "name": "BindRequest", 10411 + "type": "defined" 10412 + }, 10413 + { 10414 + "id": "bindResponse", 10415 + "name": "BindResponse", 10416 + "type": "defined" 10417 + }, 10418 + { 10419 + "id": "unbindRequest", 10420 + "name": "UnbindRequest", 10421 + "type": "defined" 10422 + }, 10423 + { 10424 + "id": "searchRequest", 10425 + "name": "SearchRequest", 10426 + "type": "defined" 10427 + }, 10428 + { 10429 + "id": "searchResEntry", 10430 + "name": "SearchResultEntry", 10431 + "type": "defined" 10432 + }, 10433 + { 10434 + "id": "searchResDone", 10435 + "name": "SearchResultDone", 10436 + "type": "defined" 10437 + }, 10438 + { 10439 + "id": "searchResRef", 10440 + "name": "SearchResultReference", 10441 + "type": "defined" 10442 + }, 10443 + { 10444 + "id": "modifyRequest", 10445 + "name": "ModifyRequest", 10446 + "type": "defined" 10447 + }, 10448 + { 10449 + "id": "modifyResponse", 10450 + "name": "ModifyResponse", 10451 + "type": "defined" 10452 + }, 10453 + { 10454 + "id": "addRequest", 10455 + "name": "AddRequest", 10456 + "type": "defined" 10457 + }, 10458 + { 10459 + "id": "addResponse", 10460 + "name": "AddResponse", 10461 + "type": "defined" 10462 + }, 10463 + { 10464 + "id": "delRequest", 10465 + "name": "DelRequest", 10466 + "type": "defined" 10467 + }, 10468 + { 10469 + "id": "delResponse", 10470 + "name": "DelResponse", 10471 + "type": "defined" 10472 + }, 10473 + { 10474 + "id": "modDNRequest", 10475 + "name": "ModifyDNRequest", 10476 + "type": "defined" 10477 + }, 10478 + { 10479 + "id": "modDNResponse", 10480 + "name": "ModifyDNResponse", 10481 + "type": "defined" 10482 + }, 10483 + { 10484 + "id": "compareRequest", 10485 + "name": "CompareRequest", 10486 + "type": "defined" 10487 + }, 10488 + { 10489 + "id": "compareResponse", 10490 + "name": "CompareResponse", 10491 + "type": "defined" 10492 + }, 10493 + { 10494 + "id": "abandonRequest", 10495 + "name": "AbandonRequest", 10496 + "type": "defined" 10497 + }, 10498 + { 10499 + "id": "extendedReq", 10500 + "name": "ExtendedRequest", 10501 + "type": "defined" 10502 + }, 10503 + { 10504 + "id": "extendedResp", 10505 + "name": "ExtendedResponse", 10506 + "type": "defined" 10507 + }, 10508 + { 10509 + "id": "intermediateResponse", 10510 + "name": "IntermediateResponse", 10511 + "type": "defined" 10512 + } 10513 + ] 10514 + }, 10515 + { 10516 + "id": "controls", 10517 + "name": "[0]", 10518 + "type": "tag", 10519 + "class": "CONTEXT", 10520 + "explicit": false, 10521 + "content": [ 10522 + { 10523 + "name": "", 10524 + "type": { 10525 + "name": "Controls", 10526 + "type": "defined" 10527 + } 10528 + } 10529 + ], 10530 + "optional": true 10531 + } 10532 + ] 10533 + } 10534 + }, 10535 + "MessageID": { 10536 + "name": "MessageID", 10537 + "type": { 10538 + "name": "INTEGER", 10539 + "type": "builtin", 10540 + "range": [ 10541 + 0, 10542 + "maxInt" 10543 + ] 10544 + } 10545 + }, 10546 + "LDAPString": { 10547 + "name": "LDAPString", 10548 + "type": { 10549 + "name": "OCTET STRING", 10550 + "type": "builtin" 10551 + } 10552 + }, 10553 + "LDAPOID": { 10554 + "name": "LDAPOID", 10555 + "type": { 10556 + "name": "OCTET STRING", 10557 + "type": "builtin" 10558 + } 10559 + }, 10560 + "LDAPDN": { 10561 + "name": "LDAPDN", 10562 + "type": { 10563 + "name": "LDAPString", 10564 + "type": "defined" 10565 + } 10566 + }, 10567 + "RelativeLDAPDN": { 10568 + "name": "RelativeLDAPDN", 10569 + "type": { 10570 + "name": "LDAPString", 10571 + "type": "defined" 10572 + } 10573 + }, 10574 + "AttributeDescription": { 10575 + "name": "AttributeDescription", 10576 + "type": { 10577 + "name": "LDAPString", 10578 + "type": "defined" 10579 + } 10580 + }, 10581 + "AttributeValue": { 10582 + "name": "AttributeValue", 10583 + "type": { 10584 + "name": "OCTET STRING", 10585 + "type": "builtin" 10586 + } 10587 + }, 10588 + "AttributeValueAssertion": { 10589 + "name": "AttributeValueAssertion", 10590 + "type": { 10591 + "name": "SEQUENCE", 10592 + "type": "builtin", 10593 + "content": [ 10594 + { 10595 + "id": "attributeDesc", 10596 + "name": "AttributeDescription", 10597 + "type": "defined" 10598 + }, 10599 + { 10600 + "id": "assertionValue", 10601 + "name": "AssertionValue", 10602 + "type": "defined" 10603 + } 10604 + ] 10605 + } 10606 + }, 10607 + "AssertionValue": { 10608 + "name": "AssertionValue", 10609 + "type": { 10610 + "name": "OCTET STRING", 10611 + "type": "builtin" 10612 + } 10613 + }, 10614 + "PartialAttribute": { 10615 + "name": "PartialAttribute", 10616 + "type": { 10617 + "name": "SEQUENCE", 10618 + "type": "builtin", 10619 + "content": [ 10620 + { 10621 + "id": "type", 10622 + "name": "AttributeDescription", 10623 + "type": "defined" 10624 + }, 10625 + { 10626 + "id": "vals", 10627 + "name": "SET", 10628 + "type": "builtin", 10629 + "typeOf": 1, 10630 + "size": [ 10631 + 1, 10632 + "MAX" 10633 + ], 10634 + "content": [ 10635 + { 10636 + "name": "AttributeValue", 10637 + "type": "defined" 10638 + } 10639 + ] 10640 + } 10641 + ] 10642 + } 10643 + }, 10644 + "MatchingRuleId": { 10645 + "name": "MatchingRuleId", 10646 + "type": { 10647 + "name": "LDAPString", 10648 + "type": "defined" 10649 + } 10650 + }, 10651 + "LDAPResult": { 10652 + "name": "LDAPResult", 10653 + "type": { 10654 + "name": "SEQUENCE", 10655 + "type": "builtin", 10656 + "content": [ 10657 + { 10658 + "id": "resultCode", 10659 + "name": "ENUMERATED", 10660 + "type": "builtin", 10661 + "content": { 10662 + "success": 0, 10663 + "operationsError": 1, 10664 + "protocolError": 2, 10665 + "timeLimitExceeded": 3, 10666 + "sizeLimitExceeded": 4, 10667 + "compareFalse": 5, 10668 + "compareTrue": 6, 10669 + "authMethodNotSupported": 7, 10670 + "strongerAuthRequired": 8, 10671 + "referral": 10, 10672 + "adminLimitExceeded": 11, 10673 + "unavailableCriticalExtension": 12, 10674 + "confidentialityRequired": 13, 10675 + "saslBindInProgress": 14, 10676 + "noSuchAttribute": 16, 10677 + "undefinedAttributeType": 17, 10678 + "inappropriateMatching": 18, 10679 + "constraintViolation": 19, 10680 + "attributeOrValueExists": 20, 10681 + "invalidAttributeSyntax": 21, 10682 + "noSuchObject": 32, 10683 + "aliasProblem": 33, 10684 + "invalidDNSyntax": 34, 10685 + "aliasDereferencingProblem": 36, 10686 + "inappropriateAuthentication": 48, 10687 + "invalidCredentials": 49, 10688 + "insufficientAccessRights": 50, 10689 + "busy": 51, 10690 + "unavailable": 52, 10691 + "unwillingToPerform": 53, 10692 + "loopDetect": 54, 10693 + "namingViolation": 64, 10694 + "objectClassViolation": 65, 10695 + "notAllowedOnNonLeaf": 66, 10696 + "notAllowedOnRDN": 67, 10697 + "entryAlreadyExists": 68, 10698 + "objectClassModsProhibited": 69, 10699 + "affectsMultipleDSAs": 71, 10700 + "other": 80 10701 + } 10702 + }, 10703 + { 10704 + "id": "matchedDN", 10705 + "name": "LDAPDN", 10706 + "type": "defined" 10707 + }, 10708 + { 10709 + "id": "diagnosticMessage", 10710 + "name": "LDAPString", 10711 + "type": "defined" 10712 + }, 10713 + { 10714 + "id": "referral", 10715 + "name": "[3]", 10716 + "type": "tag", 10717 + "class": "CONTEXT", 10718 + "explicit": false, 10719 + "content": [ 10720 + { 10721 + "name": "", 10722 + "type": { 10723 + "name": "Referral", 10724 + "type": "defined" 10725 + } 10726 + } 10727 + ], 10728 + "optional": true 10729 + } 10730 + ] 10731 + } 10732 + }, 10733 + "Referral": { 10734 + "name": "Referral", 10735 + "type": { 10736 + "name": "SEQUENCE", 10737 + "type": "builtin", 10738 + "typeOf": 1, 10739 + "size": [ 10740 + 1, 10741 + "MAX" 10742 + ], 10743 + "content": [ 10744 + { 10745 + "name": "URI", 10746 + "type": "defined" 10747 + } 10748 + ] 10749 + } 10750 + }, 10751 + "URI": { 10752 + "name": "URI", 10753 + "type": { 10754 + "name": "LDAPString", 10755 + "type": "defined" 10756 + } 10757 + }, 10758 + "Controls": { 10759 + "name": "Controls", 10760 + "type": { 10761 + "name": "SEQUENCE", 10762 + "type": "builtin", 10763 + "typeOf": 1, 10764 + "content": [ 10765 + { 10766 + "name": "Control", 10767 + "type": "defined" 10768 + } 10769 + ] 10770 + } 10771 + }, 10772 + "Control": { 10773 + "name": "Control", 10774 + "type": { 10775 + "name": "SEQUENCE", 10776 + "type": "builtin", 10777 + "content": [ 10778 + { 10779 + "id": "controlType", 10780 + "name": "LDAPOID", 10781 + "type": "defined" 10782 + }, 10783 + { 10784 + "id": "criticality", 10785 + "name": "BOOLEAN", 10786 + "type": "builtin", 10787 + "default": false 10788 + }, 10789 + { 10790 + "id": "controlValue", 10791 + "name": "OCTET STRING", 10792 + "type": "builtin", 10793 + "optional": true 10794 + } 10795 + ] 10796 + } 10797 + }, 10798 + "BindRequest": { 10799 + "name": "BindRequest", 10800 + "type": { 10801 + "name": "Application 0", 10802 + "type": "tag", 10803 + "class": "APPLICATION", 10804 + "explicit": false, 10805 + "content": [ 10806 + { 10807 + "name": "", 10808 + "type": { 10809 + "name": "SEQUENCE", 10810 + "type": "builtin", 10811 + "content": [ 10812 + { 10813 + "id": "version", 10814 + "name": "INTEGER", 10815 + "type": "builtin", 10816 + "range": [ 10817 + 1, 10818 + 127 10819 + ] 10820 + }, 10821 + { 10822 + "id": "name", 10823 + "name": "LDAPDN", 10824 + "type": "defined" 10825 + }, 10826 + { 10827 + "id": "authentication", 10828 + "name": "AuthenticationChoice", 10829 + "type": "defined" 10830 + } 10831 + ] 10832 + } 10833 + } 10834 + ] 10835 + } 10836 + }, 10837 + "AuthenticationChoice": { 10838 + "name": "AuthenticationChoice", 10839 + "type": { 10840 + "name": "CHOICE", 10841 + "type": "builtin", 10842 + "content": [ 10843 + { 10844 + "id": "simple", 10845 + "name": "[0]", 10846 + "type": "tag", 10847 + "class": "CONTEXT", 10848 + "explicit": false, 10849 + "content": [ 10850 + { 10851 + "name": "", 10852 + "type": { 10853 + "name": "OCTET STRING", 10854 + "type": "builtin" 10855 + } 10856 + } 10857 + ] 10858 + }, 10859 + { 10860 + "id": "sasl", 10861 + "name": "[3]", 10862 + "type": "tag", 10863 + "class": "CONTEXT", 10864 + "explicit": false, 10865 + "content": [ 10866 + { 10867 + "name": "", 10868 + "type": { 10869 + "name": "SaslCredentials", 10870 + "type": "defined" 10871 + } 10872 + } 10873 + ] 10874 + } 10875 + ] 10876 + } 10877 + }, 10878 + "SaslCredentials": { 10879 + "name": "SaslCredentials", 10880 + "type": { 10881 + "name": "SEQUENCE", 10882 + "type": "builtin", 10883 + "content": [ 10884 + { 10885 + "id": "mechanism", 10886 + "name": "LDAPString", 10887 + "type": "defined" 10888 + }, 10889 + { 10890 + "id": "credentials", 10891 + "name": "OCTET STRING", 10892 + "type": "builtin", 10893 + "optional": true 10894 + } 10895 + ] 10896 + } 10897 + }, 10898 + "BindResponse": { 10899 + "name": "BindResponse", 10900 + "type": { 10901 + "name": "ANY", 10902 + "type": "builtin" 10903 + } 10904 + }, 10905 + "UnbindRequest": { 10906 + "name": "UnbindRequest", 10907 + "type": { 10908 + "name": "Application 2", 10909 + "type": "tag", 10910 + "class": "APPLICATION", 10911 + "explicit": false, 10912 + "content": [ 10913 + { 10914 + "name": "", 10915 + "type": { 10916 + "name": "NULL", 10917 + "type": "builtin" 10918 + } 10919 + } 10920 + ] 10921 + } 10922 + }, 10923 + "SearchRequest": { 10924 + "name": "SearchRequest", 10925 + "type": { 10926 + "name": "Application 3", 10927 + "type": "tag", 10928 + "class": "APPLICATION", 10929 + "explicit": false, 10930 + "content": [ 10931 + { 10932 + "name": "", 10933 + "type": { 10934 + "name": "SEQUENCE", 10935 + "type": "builtin", 10936 + "content": [ 10937 + { 10938 + "id": "baseObject", 10939 + "name": "LDAPDN", 10940 + "type": "defined" 10941 + }, 10942 + { 10943 + "id": "scope", 10944 + "name": "ENUMERATED", 10945 + "type": "builtin", 10946 + "content": { 10947 + "baseObject": 0, 10948 + "singleLevel": 1, 10949 + "wholeSubtree": 2 10950 + } 10951 + }, 10952 + { 10953 + "id": "derefAliases", 10954 + "name": "ENUMERATED", 10955 + "type": "builtin", 10956 + "content": { 10957 + "neverDerefAliases": 0, 10958 + "derefInSearching": 1, 10959 + "derefFindingBaseObj": 2, 10960 + "derefAlways": 3 10961 + } 10962 + }, 10963 + { 10964 + "id": "sizeLimit", 10965 + "name": "INTEGER", 10966 + "type": "builtin", 10967 + "range": [ 10968 + 0, 10969 + "maxInt" 10970 + ] 10971 + }, 10972 + { 10973 + "id": "timeLimit", 10974 + "name": "INTEGER", 10975 + "type": "builtin", 10976 + "range": [ 10977 + 0, 10978 + "maxInt" 10979 + ] 10980 + }, 10981 + { 10982 + "id": "typesOnly", 10983 + "name": "BOOLEAN", 10984 + "type": "builtin" 10985 + }, 10986 + { 10987 + "id": "filter", 10988 + "name": "Filter", 10989 + "type": "defined" 10990 + }, 10991 + { 10992 + "id": "attributes", 10993 + "name": "AttributeSelection", 10994 + "type": "defined" 10995 + } 10996 + ] 10997 + } 10998 + } 10999 + ] 11000 + } 11001 + }, 11002 + "AttributeSelection": { 11003 + "name": "AttributeSelection", 11004 + "type": { 11005 + "name": "SEQUENCE", 11006 + "type": "builtin", 11007 + "typeOf": 1, 11008 + "content": [ 11009 + { 11010 + "name": "LDAPString", 11011 + "type": "defined" 11012 + } 11013 + ] 11014 + } 11015 + }, 11016 + "Filter": { 11017 + "name": "Filter", 11018 + "type": { 11019 + "name": "CHOICE", 11020 + "type": "builtin", 11021 + "content": [ 11022 + { 11023 + "id": "and", 11024 + "name": "[0]", 11025 + "type": "tag", 11026 + "class": "CONTEXT", 11027 + "explicit": false, 11028 + "content": [ 11029 + { 11030 + "name": "", 11031 + "type": { 11032 + "name": "SET", 11033 + "type": "builtin", 11034 + "typeOf": 1, 11035 + "size": [ 11036 + 1, 11037 + "MAX" 11038 + ], 11039 + "content": [ 11040 + { 11041 + "name": "Filter", 11042 + "type": "defined" 11043 + } 11044 + ] 11045 + } 11046 + } 11047 + ] 11048 + }, 11049 + { 11050 + "id": "or", 11051 + "name": "[1]", 11052 + "type": "tag", 11053 + "class": "CONTEXT", 11054 + "explicit": false, 11055 + "content": [ 11056 + { 11057 + "name": "", 11058 + "type": { 11059 + "name": "SET", 11060 + "type": "builtin", 11061 + "typeOf": 1, 11062 + "size": [ 11063 + 1, 11064 + "MAX" 11065 + ], 11066 + "content": [ 11067 + { 11068 + "name": "Filter", 11069 + "type": "defined" 11070 + } 11071 + ] 11072 + } 11073 + } 11074 + ] 11075 + }, 11076 + { 11077 + "id": "not", 11078 + "name": "[2]", 11079 + "type": "tag", 11080 + "class": "CONTEXT", 11081 + "explicit": false, 11082 + "content": [ 11083 + { 11084 + "name": "", 11085 + "type": { 11086 + "name": "Filter", 11087 + "type": "defined" 11088 + } 11089 + } 11090 + ] 11091 + }, 11092 + { 11093 + "id": "equalityMatch", 11094 + "name": "[3]", 11095 + "type": "tag", 11096 + "class": "CONTEXT", 11097 + "explicit": false, 11098 + "content": [ 11099 + { 11100 + "name": "", 11101 + "type": { 11102 + "name": "AttributeValueAssertion", 11103 + "type": "defined" 11104 + } 11105 + } 11106 + ] 11107 + }, 11108 + { 11109 + "id": "substrings", 11110 + "name": "[4]", 11111 + "type": "tag", 11112 + "class": "CONTEXT", 11113 + "explicit": false, 11114 + "content": [ 11115 + { 11116 + "name": "", 11117 + "type": { 11118 + "name": "SubstringFilter", 11119 + "type": "defined" 11120 + } 11121 + } 11122 + ] 11123 + }, 11124 + { 11125 + "id": "greaterOrEqual", 11126 + "name": "[5]", 11127 + "type": "tag", 11128 + "class": "CONTEXT", 11129 + "explicit": false, 11130 + "content": [ 11131 + { 11132 + "name": "", 11133 + "type": { 11134 + "name": "AttributeValueAssertion", 11135 + "type": "defined" 11136 + } 11137 + } 11138 + ] 11139 + }, 11140 + { 11141 + "id": "lessOrEqual", 11142 + "name": "[6]", 11143 + "type": "tag", 11144 + "class": "CONTEXT", 11145 + "explicit": false, 11146 + "content": [ 11147 + { 11148 + "name": "", 11149 + "type": { 11150 + "name": "AttributeValueAssertion", 11151 + "type": "defined" 11152 + } 11153 + } 11154 + ] 11155 + }, 11156 + { 11157 + "id": "present", 11158 + "name": "[7]", 11159 + "type": "tag", 11160 + "class": "CONTEXT", 11161 + "explicit": false, 11162 + "content": [ 11163 + { 11164 + "name": "", 11165 + "type": { 11166 + "name": "AttributeDescription", 11167 + "type": "defined" 11168 + } 11169 + } 11170 + ] 11171 + }, 11172 + { 11173 + "id": "approxMatch", 11174 + "name": "[8]", 11175 + "type": "tag", 11176 + "class": "CONTEXT", 11177 + "explicit": false, 11178 + "content": [ 11179 + { 11180 + "name": "", 11181 + "type": { 11182 + "name": "AttributeValueAssertion", 11183 + "type": "defined" 11184 + } 11185 + } 11186 + ] 11187 + }, 11188 + { 11189 + "id": "extensibleMatch", 11190 + "name": "[9]", 11191 + "type": "tag", 11192 + "class": "CONTEXT", 11193 + "explicit": false, 11194 + "content": [ 11195 + { 11196 + "name": "", 11197 + "type": { 11198 + "name": "MatchingRuleAssertion", 11199 + "type": "defined" 11200 + } 11201 + } 11202 + ] 11203 + } 11204 + ] 11205 + } 11206 + }, 11207 + "SubstringFilter": { 11208 + "name": "SubstringFilter", 11209 + "type": { 11210 + "name": "SEQUENCE", 11211 + "type": "builtin", 11212 + "content": [ 11213 + { 11214 + "id": "type", 11215 + "name": "AttributeDescription", 11216 + "type": "defined" 11217 + }, 11218 + { 11219 + "id": "substrings", 11220 + "name": "SEQUENCE", 11221 + "type": "builtin", 11222 + "typeOf": 1, 11223 + "size": [ 11224 + 1, 11225 + "MAX" 11226 + ], 11227 + "content": [ 11228 + { 11229 + "name": "CHOICE", 11230 + "type": "builtin", 11231 + "content": [ 11232 + { 11233 + "id": "initial", 11234 + "name": "[0]", 11235 + "type": "tag", 11236 + "class": "CONTEXT", 11237 + "explicit": false, 11238 + "content": [ 11239 + { 11240 + "name": "", 11241 + "type": { 11242 + "name": "AssertionValue", 11243 + "type": "defined" 11244 + } 11245 + } 11246 + ] 11247 + }, 11248 + { 11249 + "id": "any", 11250 + "name": "[1]", 11251 + "type": "tag", 11252 + "class": "CONTEXT", 11253 + "explicit": false, 11254 + "content": [ 11255 + { 11256 + "name": "", 11257 + "type": { 11258 + "name": "AssertionValue", 11259 + "type": "defined" 11260 + } 11261 + } 11262 + ] 11263 + }, 11264 + { 11265 + "id": "final", 11266 + "name": "[2]", 11267 + "type": "tag", 11268 + "class": "CONTEXT", 11269 + "explicit": false, 11270 + "content": [ 11271 + { 11272 + "name": "", 11273 + "type": { 11274 + "name": "AssertionValue", 11275 + "type": "defined" 11276 + } 11277 + } 11278 + ] 11279 + } 11280 + ] 11281 + } 11282 + ] 11283 + } 11284 + ] 11285 + } 11286 + }, 11287 + "MatchingRuleAssertion": { 11288 + "name": "MatchingRuleAssertion", 11289 + "type": { 11290 + "name": "SEQUENCE", 11291 + "type": "builtin", 11292 + "content": [ 11293 + { 11294 + "id": "matchingRule", 11295 + "name": "[1]", 11296 + "type": "tag", 11297 + "class": "CONTEXT", 11298 + "explicit": false, 11299 + "content": [ 11300 + { 11301 + "name": "", 11302 + "type": { 11303 + "name": "MatchingRuleId", 11304 + "type": "defined" 11305 + } 11306 + } 11307 + ], 11308 + "optional": true 11309 + }, 11310 + { 11311 + "id": "type", 11312 + "name": "[2]", 11313 + "type": "tag", 11314 + "class": "CONTEXT", 11315 + "explicit": false, 11316 + "content": [ 11317 + { 11318 + "name": "", 11319 + "type": { 11320 + "name": "AttributeDescription", 11321 + "type": "defined" 11322 + } 11323 + } 11324 + ], 11325 + "optional": true 11326 + }, 11327 + { 11328 + "id": "matchValue", 11329 + "name": "[3]", 11330 + "type": "tag", 11331 + "class": "CONTEXT", 11332 + "explicit": false, 11333 + "content": [ 11334 + { 11335 + "name": "", 11336 + "type": { 11337 + "name": "AssertionValue", 11338 + "type": "defined" 11339 + } 11340 + } 11341 + ] 11342 + }, 11343 + { 11344 + "id": "dnAttributes", 11345 + "name": "[4]", 11346 + "type": "tag", 11347 + "class": "CONTEXT", 11348 + "explicit": false, 11349 + "content": [ 11350 + { 11351 + "name": "", 11352 + "type": { 11353 + "name": "BOOLEAN", 11354 + "type": "builtin" 11355 + } 11356 + } 11357 + ], 11358 + "default": false 11359 + } 11360 + ] 11361 + } 11362 + }, 11363 + "SearchResultEntry": { 11364 + "name": "SearchResultEntry", 11365 + "type": { 11366 + "name": "Application 4", 11367 + "type": "tag", 11368 + "class": "APPLICATION", 11369 + "explicit": false, 11370 + "content": [ 11371 + { 11372 + "name": "", 11373 + "type": { 11374 + "name": "SEQUENCE", 11375 + "type": "builtin", 11376 + "content": [ 11377 + { 11378 + "id": "objectName", 11379 + "name": "LDAPDN", 11380 + "type": "defined" 11381 + }, 11382 + { 11383 + "id": "attributes", 11384 + "name": "PartialAttributeList", 11385 + "type": "defined" 11386 + } 11387 + ] 11388 + } 11389 + } 11390 + ] 11391 + } 11392 + }, 11393 + "PartialAttributeList": { 11394 + "name": "PartialAttributeList", 11395 + "type": { 11396 + "name": "SEQUENCE", 11397 + "type": "builtin", 11398 + "typeOf": 1, 11399 + "content": [ 11400 + { 11401 + "name": "PartialAttribute", 11402 + "type": "defined" 11403 + } 11404 + ] 11405 + } 11406 + }, 11407 + "SearchResultReference": { 11408 + "name": "SearchResultReference", 11409 + "type": { 11410 + "name": "Application 19", 11411 + "type": "tag", 11412 + "class": "APPLICATION", 11413 + "explicit": false, 11414 + "content": [ 11415 + { 11416 + "name": "", 11417 + "type": { 11418 + "name": "SEQUENCE", 11419 + "type": "builtin", 11420 + "typeOf": 1, 11421 + "size": [ 11422 + 1, 11423 + "MAX" 11424 + ], 11425 + "content": [ 11426 + { 11427 + "name": "URI", 11428 + "type": "defined" 11429 + } 11430 + ] 11431 + } 11432 + } 11433 + ] 11434 + } 11435 + }, 11436 + "SearchResultDone": { 11437 + "name": "SearchResultDone", 11438 + "type": { 11439 + "name": "Application 5", 11440 + "type": "tag", 11441 + "class": "APPLICATION", 11442 + "explicit": false, 11443 + "content": [ 11444 + { 11445 + "name": "", 11446 + "type": { 11447 + "name": "LDAPResult", 11448 + "type": "defined" 11449 + } 11450 + } 11451 + ] 11452 + } 11453 + }, 11454 + "ModifyRequest": { 11455 + "name": "ModifyRequest", 11456 + "type": { 11457 + "name": "Application 6", 11458 + "type": "tag", 11459 + "class": "APPLICATION", 11460 + "explicit": false, 11461 + "content": [ 11462 + { 11463 + "name": "", 11464 + "type": { 11465 + "name": "SEQUENCE", 11466 + "type": "builtin", 11467 + "content": [ 11468 + { 11469 + "id": "object", 11470 + "name": "LDAPDN", 11471 + "type": "defined" 11472 + }, 11473 + { 11474 + "id": "changes", 11475 + "name": "SEQUENCE", 11476 + "type": "builtin", 11477 + "typeOf": 1, 11478 + "content": [ 11479 + { 11480 + "name": "SEQUENCE", 11481 + "type": "builtin", 11482 + "content": [ 11483 + { 11484 + "id": "operation", 11485 + "name": "ENUMERATED", 11486 + "type": "builtin", 11487 + "content": { 11488 + "add": 0, 11489 + "delete": 1, 11490 + "replace": 2 11491 + } 11492 + }, 11493 + { 11494 + "id": "modification", 11495 + "name": "PartialAttribute", 11496 + "type": "defined" 11497 + } 11498 + ] 11499 + } 11500 + ] 11501 + } 11502 + ] 11503 + } 11504 + } 11505 + ] 11506 + } 11507 + }, 11508 + "ModifyResponse": { 11509 + "name": "ModifyResponse", 11510 + "type": { 11511 + "name": "Application 7", 11512 + "type": "tag", 11513 + "class": "APPLICATION", 11514 + "explicit": false, 11515 + "content": [ 11516 + { 11517 + "name": "", 11518 + "type": { 11519 + "name": "LDAPResult", 11520 + "type": "defined" 11521 + } 11522 + } 11523 + ] 11524 + } 11525 + }, 11526 + "AddRequest": { 11527 + "name": "AddRequest", 11528 + "type": { 11529 + "name": "Application 8", 11530 + "type": "tag", 11531 + "class": "APPLICATION", 11532 + "explicit": false, 11533 + "content": [ 11534 + { 11535 + "name": "", 11536 + "type": { 11537 + "name": "SEQUENCE", 11538 + "type": "builtin", 11539 + "content": [ 11540 + { 11541 + "id": "entry", 11542 + "name": "LDAPDN", 11543 + "type": "defined" 11544 + }, 11545 + { 11546 + "id": "attributes", 11547 + "name": "AttributeList", 11548 + "type": "defined" 11549 + } 11550 + ] 11551 + } 11552 + } 11553 + ] 11554 + } 11555 + }, 11556 + "AttributeList": { 11557 + "name": "AttributeList", 11558 + "type": { 11559 + "name": "SEQUENCE", 11560 + "type": "builtin", 11561 + "typeOf": 1, 11562 + "content": [ 11563 + { 11564 + "name": "Attribute", 11565 + "type": "defined" 11566 + } 11567 + ] 11568 + } 11569 + }, 11570 + "AddResponse": { 11571 + "name": "AddResponse", 11572 + "type": { 11573 + "name": "Application 9", 11574 + "type": "tag", 11575 + "class": "APPLICATION", 11576 + "explicit": false, 11577 + "content": [ 11578 + { 11579 + "name": "", 11580 + "type": { 11581 + "name": "LDAPResult", 11582 + "type": "defined" 11583 + } 11584 + } 11585 + ] 11586 + } 11587 + }, 11588 + "DelRequest": { 11589 + "name": "DelRequest", 11590 + "type": { 11591 + "name": "Application 10", 11592 + "type": "tag", 11593 + "class": "APPLICATION", 11594 + "explicit": false, 11595 + "content": [ 11596 + { 11597 + "name": "", 11598 + "type": { 11599 + "name": "LDAPDN", 11600 + "type": "defined" 11601 + } 11602 + } 11603 + ] 11604 + } 11605 + }, 11606 + "DelResponse": { 11607 + "name": "DelResponse", 11608 + "type": { 11609 + "name": "Application 11", 11610 + "type": "tag", 11611 + "class": "APPLICATION", 11612 + "explicit": false, 11613 + "content": [ 11614 + { 11615 + "name": "", 11616 + "type": { 11617 + "name": "LDAPResult", 11618 + "type": "defined" 11619 + } 11620 + } 11621 + ] 11622 + } 11623 + }, 11624 + "ModifyDNRequest": { 11625 + "name": "ModifyDNRequest", 11626 + "type": { 11627 + "name": "Application 12", 11628 + "type": "tag", 11629 + "class": "APPLICATION", 11630 + "explicit": false, 11631 + "content": [ 11632 + { 11633 + "name": "", 11634 + "type": { 11635 + "name": "SEQUENCE", 11636 + "type": "builtin", 11637 + "content": [ 11638 + { 11639 + "id": "entry", 11640 + "name": "LDAPDN", 11641 + "type": "defined" 11642 + }, 11643 + { 11644 + "id": "newrdn", 11645 + "name": "RelativeLDAPDN", 11646 + "type": "defined" 11647 + }, 11648 + { 11649 + "id": "deleteoldrdn", 11650 + "name": "BOOLEAN", 11651 + "type": "builtin" 11652 + }, 11653 + { 11654 + "id": "newSuperior", 11655 + "name": "[0]", 11656 + "type": "tag", 11657 + "class": "CONTEXT", 11658 + "explicit": false, 11659 + "content": [ 11660 + { 11661 + "name": "", 11662 + "type": { 11663 + "name": "LDAPDN", 11664 + "type": "defined" 11665 + } 11666 + } 11667 + ], 11668 + "optional": true 11669 + } 11670 + ] 11671 + } 11672 + } 11673 + ] 11674 + } 11675 + }, 11676 + "ModifyDNResponse": { 11677 + "name": "ModifyDNResponse", 11678 + "type": { 11679 + "name": "Application 13", 11680 + "type": "tag", 11681 + "class": "APPLICATION", 11682 + "explicit": false, 11683 + "content": [ 11684 + { 11685 + "name": "", 11686 + "type": { 11687 + "name": "LDAPResult", 11688 + "type": "defined" 11689 + } 11690 + } 11691 + ] 11692 + } 11693 + }, 11694 + "CompareRequest": { 11695 + "name": "CompareRequest", 11696 + "type": { 11697 + "name": "Application 14", 11698 + "type": "tag", 11699 + "class": "APPLICATION", 11700 + "explicit": false, 11701 + "content": [ 11702 + { 11703 + "name": "", 11704 + "type": { 11705 + "name": "SEQUENCE", 11706 + "type": "builtin", 11707 + "content": [ 11708 + { 11709 + "id": "entry", 11710 + "name": "LDAPDN", 11711 + "type": "defined" 11712 + }, 11713 + { 11714 + "id": "ava", 11715 + "name": "AttributeValueAssertion", 11716 + "type": "defined" 11717 + } 11718 + ] 11719 + } 11720 + } 11721 + ] 11722 + } 11723 + }, 11724 + "CompareResponse": { 11725 + "name": "CompareResponse", 11726 + "type": { 11727 + "name": "Application 15", 11728 + "type": "tag", 11729 + "class": "APPLICATION", 11730 + "explicit": false, 11731 + "content": [ 11732 + { 11733 + "name": "", 11734 + "type": { 11735 + "name": "LDAPResult", 11736 + "type": "defined" 11737 + } 11738 + } 11739 + ] 11740 + } 11741 + }, 11742 + "AbandonRequest": { 11743 + "name": "AbandonRequest", 11744 + "type": { 11745 + "name": "Application 16", 11746 + "type": "tag", 11747 + "class": "APPLICATION", 11748 + "explicit": false, 11749 + "content": [ 11750 + { 11751 + "name": "", 11752 + "type": { 11753 + "name": "MessageID", 11754 + "type": "defined" 11755 + } 11756 + } 11757 + ] 11758 + } 11759 + }, 11760 + "ExtendedRequest": { 11761 + "name": "ExtendedRequest", 11762 + "type": { 11763 + "name": "Application 23", 11764 + "type": "tag", 11765 + "class": "APPLICATION", 11766 + "explicit": false, 11767 + "content": [ 11768 + { 11769 + "name": "", 11770 + "type": { 11771 + "name": "SEQUENCE", 11772 + "type": "builtin", 11773 + "content": [ 11774 + { 11775 + "id": "requestName", 11776 + "name": "[0]", 11777 + "type": "tag", 11778 + "class": "CONTEXT", 11779 + "explicit": false, 11780 + "content": [ 11781 + { 11782 + "name": "", 11783 + "type": { 11784 + "name": "LDAPOID", 11785 + "type": "defined" 11786 + } 11787 + } 11788 + ] 11789 + }, 11790 + { 11791 + "id": "requestValue", 11792 + "name": "[1]", 11793 + "type": "tag", 11794 + "class": "CONTEXT", 11795 + "explicit": false, 11796 + "content": [ 11797 + { 11798 + "name": "", 11799 + "type": { 11800 + "name": "OCTET STRING", 11801 + "type": "builtin" 11802 + } 11803 + } 11804 + ], 11805 + "optional": true 11806 + } 11807 + ] 11808 + } 11809 + } 11810 + ] 11811 + } 11812 + }, 11813 + "ExtendedResponse": { 11814 + "name": "ExtendedResponse", 11815 + "type": { 11816 + "name": "ANY", 11817 + "type": "builtin" 11818 + } 11819 + }, 11820 + "IntermediateResponse": { 11821 + "name": "IntermediateResponse", 11822 + "type": { 11823 + "name": "Application 25", 11824 + "type": "tag", 11825 + "class": "APPLICATION", 11826 + "explicit": false, 11827 + "content": [ 11828 + { 11829 + "name": "", 11830 + "type": { 11831 + "name": "SEQUENCE", 11832 + "type": "builtin", 11833 + "content": [ 11834 + { 11835 + "id": "responseName", 11836 + "name": "[0]", 11837 + "type": "tag", 11838 + "class": "CONTEXT", 11839 + "explicit": false, 11840 + "content": [ 11841 + { 11842 + "name": "", 11843 + "type": { 11844 + "name": "LDAPOID", 11845 + "type": "defined" 11846 + } 11847 + } 11848 + ], 11849 + "optional": true 11850 + }, 11851 + { 11852 + "id": "responseValue", 11853 + "name": "[1]", 11854 + "type": "tag", 11855 + "class": "CONTEXT", 11856 + "explicit": false, 11857 + "content": [ 11858 + { 11859 + "name": "", 11860 + "type": { 11861 + "name": "OCTET STRING", 11862 + "type": "builtin" 11863 + } 11864 + } 11865 + ], 11866 + "optional": true 11867 + } 11868 + ] 11869 + } 11870 + } 11871 + ] 10385 11872 } 10386 11873 } 10387 11874 }
+7
tags.js
··· 1 1 export const tags = { 2 + "2.1.1": "2025-10-24", 3 + "2.1.0": "2025-08-03", 4 + "2.0.6": "2025-07-28", 5 + "2.0.5": "2025-04-12", 6 + "2.0.4": "2024-05-08", 7 + "2.0.3": "2024-05-06", 8 + "2.0.2": "2024-04-20", 2 9 "2.0.1": "2024-03-28", 3 10 "2.0.0": "2024-03-26", 4 11 "1.3.0": "2024-03-26",
+172 -38
test.js
··· 1 1 #!/usr/bin/env node 2 2 3 - import { ASN1 } from './asn1.js'; 3 + import * as fs from 'fs'; // 'node:fs' doesn't work on NodeJS 14.5.0 4 + import { ASN1, Stream } from './asn1.js'; 5 + import { Defs } from './defs.js'; 4 6 import { Hex } from './hex.js'; 7 + import { Base64 } from './base64.js'; 8 + import { createPatch } from 'diff'; 5 9 6 - const 7 - all = (process.argv[2] == 'all'); 10 + const all = (process.argv[2] == 'all'); 11 + 12 + /** @type {Array<Tests>} */ 13 + const tests = []; 14 + 15 + const stats = { 16 + run: 0, 17 + error: 0, 18 + }; 19 + 20 + function diff(str1, str2) { 21 + let s = createPatch('test', str1, str2, null, null, { context: 2 }); 22 + s = s.slice(s.indexOf('@@'), -1); 23 + s = s.replace(/^@@.*/mg, '\x1B[34m$&\x1B[39m'); 24 + s = s.replace(/^-.*/mg, '\x1B[31m$&\x1B[39m'); 25 + s = s.replace(/^\+.*/mg, '\x1B[32m$&\x1B[39m'); 26 + return s; 27 + } 28 + 29 + /** 30 + * A class for managing and executing tests. 31 + */ 32 + class Tests { 33 + /** 34 + * The title of the test suite. 35 + * @type {string} 36 + */ 37 + title; 38 + 39 + /** 40 + * An array to store test data. 41 + * @type {Array<unknown>} 42 + */ 43 + data; 44 + 45 + /** 46 + * Checks a row of test data. 47 + * @param {Function} t - How to test a row of data. 48 + */ 49 + checkRow; 50 + 51 + /** 52 + * Constructs a new Tests instance. 53 + * @param {string} title - The title of the test suite. 54 + * @param {Function} checkRow - A function to check each row of data. 55 + * @param {Array<unknown>} data - The test data to be processed. 56 + */ 57 + constructor(title, checkRow, data) { 58 + this.title = title; 59 + this.checkRow = checkRow; 60 + this.data = data; 61 + } 8 62 9 - const tests = [ 63 + /** 64 + * Executes the tests and checks their results for all rows. 65 + */ 66 + checkAll() { 67 + if (all) console.log('\x1B[1m\x1B[34m' + this.title + '\x1B[39m\x1B[22m'); 68 + for (const t of this.data) 69 + this.checkRow(t); 70 + } 71 + 72 + /** 73 + * Prints the result of a test, indicating if it passed or failed. 74 + * @param {unknown} result The actual result of the test. 75 + * @param {unknown} expected The expected result of the test. 76 + * @param {string} comment A comment describing the test. 77 + */ 78 + checkResult(result, expected, comment) { 79 + ++stats.run; 80 + if ((typeof expected != 'string' && !result) || result == expected) { 81 + if (all) console.log('\x1B[1m\x1B[32mOK \x1B[39m\x1B[22m ' + comment); 82 + } else { 83 + ++stats.error; 84 + console.log('\x1B[1m\x1B[31mERR\x1B[39m\x1B[22m ' + comment); 85 + if (!result) result = '(empty)'; 86 + if (typeof expected != 'string') { 87 + console.log(' ' + result); 88 + } else if (result.length > 100) { 89 + console.log(' \x1B[1m\x1B[34mDIF\x1B[39m\x1B[22m ' + diff(result, expected.toString()).replace(/\n/g, '\n ')); 90 + } else { 91 + console.log(' \x1B[1m\x1B[34mEXP\x1B[39m\x1B[22m ' + expected.toString().replace(/\n/g, '\n ')); 92 + console.log(' \x1B[1m\x1B[33mGOT\x1B[39m\x1B[22m ' + result.replace(/\n/g, '\n ')); 93 + } 94 + } 95 + } 96 + } 97 + 98 + tests.push(new Tests('ASN.1', function (t) { 99 + const input = t[0], 100 + expected = t[1], 101 + comment = t[2]; 102 + let result; 103 + try { 104 + let node = ASN1.decode(Hex.decode(input)); 105 + if (typeof expected == 'function') 106 + result = expected(node); 107 + else 108 + result = node.content(); 109 + //TODO: check structure, not only first level content 110 + } catch (e) { 111 + result = 'Exception:\n' + e; 112 + } 113 + if (expected instanceof RegExp) 114 + result = expected.test(result) ? null : 'does not match'; 115 + this.checkResult(result, expected, comment); 116 + }, [ 10 117 // RSA Laboratories technical notes from https://luca.ntop.org/Teaching/Appunti/asn1.html 11 118 ['0304066E5DC0', '(18 bit)\n011011100101110111', 'ntop, bit string: DER encoding'], 12 119 ['0304066E5DE0', '(18 bit)\n011011100101110111', 'ntop, bit string: padded with "100000"'], ··· 75 182 ['0D04C27B0302','8571.3.2', 'Relative OID from ISO/IEC 8825-1:2002 8.20.5'], 76 183 // UTF-8 77 184 ['0C0E4C61706FE280997320F09F9A972E', 'Lapoโ€™s ๐Ÿš—.', 'UTF-8 4-byte sequence'], 78 - // T-REC-X.690-201508 185 + // T-REC-X.690-202102 79 186 ['0307040A3B5F291CD0', '(44 bit)\n00001010001110110101111100101001000111001101', 'Example 8.6.4.2: bit string (primitive encoding)'], 80 187 ['23800303000A3B0305045F291CD00000', '(44 bit)\n00001010001110110101111100101001000111001101', 'Example 8.6.4.2: bit string (constructed encoding)'], 188 + ['0603883703', '2.999.3', 'Example 8.19.5: object identifier'], 189 + // X.690 section 8.2.1 โ€œThe contents octets shall consist of a single octet.โ€ 190 + ['010100', 'false', 'Boolean with correct length (false)'], 191 + ['010101', 'true', 'Boolean with correct length (true)'], 192 + ['0100', 'invalid length 0', 'Boolean with zero length'], 193 + ['01020000', 'invalid length 2', 'Boolean with excessive length'], 194 + // X.690 section 8.3.1 โ€œThe contents octets shall consist of one or more octets.โ€ 195 + ['020100', '0', 'Integer with correct length'], 196 + ['0200', 'invalid length 0', 'Integer with zero length'], 197 + // X.690 section 8.19.4 kinda imples that the minimum number of components is 2 198 + ['0600', 'invalid length 0', 'Object identifier with zero length'], 199 + ['060100', '0.0', 'Object identifier with minimal (?) length'], 81 200 // avoid past bugs 82 201 ['23800303000A3B230A0302005F030404291CD00000', '(44 bit)\n00001010001110110101111100101001000111001101', 'Bit string (recursive constructed)'], 83 202 ['0348003045022100DE601E573DAFB59BC551D58E3E7B9EDA0612DD0112805A2217B734759B884417022067C3FDE60780D41C1D7A3B90291F3D39C4DC2F206DCCBA2F982C06B67C09B232', '(568 bit)\n0011000001000101000000100010000100000000110111100110000000011110010101110011110110101111101101011001101111000101010100011101010110001110001111100111101110011110110110100000011000010010110111010000000100010010100000000101101000100010000101111011011100110100011101011001101110001000010001000001011100000010001000000110011111000011111111011110011000000111100000001101010000011100000111010111101000111011100100000010100100011111001111010011100111000100110111000010111100100000011011011100110010111010001011111001100000101100000001101011011001111100000010011011001000110010', 'not constructed, but contains structures'], ··· 88 207 ['181331393835313130363231303632372E332B3134', '1985-11-06 21:06:27.3 UTC+14:00', 'UTC offset +13 and +14'], // GitHub issue #54 89 208 ['032100171E83C1B251803F86DD01E9CFA886BE89A7316D8372649AC2231EC669F81A84', n => { if (n.sub != null) return 'Should not decode content: ' + n.sub[0].content(); }, 'Key that resembles an UTCTime'], // GitHub issue #79 90 209 ['171E83C1B251803F86DD01E9CFA886BE89A7316D8372649AC2231EC669F81A84', /^Exception:\nError: Unrecognized time: /, 'Invalid UTCTime'], // GitHub issue #79 91 - ]; 210 + ])); 92 211 93 - let 94 - run = 0, 95 - expErr = 0, 96 - error = 0; 97 - tests.forEach(function (t) { 98 - const input = t[0], 99 - expected = t[1], 100 - comment = t[2]; 101 - let result; 102 - try { 103 - let node = ASN1.decode(Hex.decode(input)); 104 - if (typeof expected == 'function') 105 - result = expected(node); 106 - else 107 - result = node.content(); 108 - //TODO: check structure, not only first level content 109 - } catch (e) { 110 - result = 'Exception:\n' + e; 212 + tests.push(new Tests('Dump of examples', function () { 213 + const examples = fs.readdirSync('examples/').filter(f => f.endsWith('.dump')); 214 + for (const example of examples) { 215 + const filename = example.slice(0, -5); // Remove '.dump' suffix 216 + const expected = fs.readFileSync('examples/' + example, 'utf8'); 217 + let data = fs.readFileSync('examples/' + filename); 218 + data = Base64.unarmor(data); 219 + let node = ASN1.decode(data); 220 + const types = Defs.commonTypes 221 + .map(type => { 222 + const stats = Defs.match(node, type); 223 + return { type, match: stats.recognized / stats.total }; 224 + }) 225 + .sort((a, b) => b.match - a.match); 226 + Defs.match(node, types[0].type); 227 + let result = node.toPrettyString(); 228 + this.checkResult(result, expected, 'Dump of examples/' + filename); 111 229 } 112 - if (expected instanceof RegExp) 113 - result = expected.test(result) ? null : 'does not match'; 114 - ++run; 115 - if (!result || result == expected) { 116 - if (all) console.log('\x1B[1m\x1B[32mOK \x1B[39m\x1B[22m ' + comment); 117 - } else { 118 - ++error; 119 - console.log('\x1B[1m\x1B[31mERR\x1B[39m\x1B[22m ' + comment); 120 - console.log(' \x1B[1m\x1B[34mEXP\x1B[39m\x1B[22m ' + expected.toString().replace(/\n/g, '\n ')); 121 - console.log(' \x1B[1m\x1B[33mGOT\x1B[39m\x1B[22m ' + result.replace(/\n/g, '\n ')); 122 - } 123 - }); 124 - console.log(run + ' tested, ' + expErr + ' expected, ' + error + ' errors.'); 125 - process.exit(error ? 1 : 0); 230 + }, [ 231 + [0], 232 + ])); 233 + 234 + tests.push(new Tests('Base64', function (t) { 235 + let bin = Base64.decode(t); 236 + let url = new Stream(bin, 0).b64Dump(0, bin.length); 237 + // check base64url encoding 238 + this.checkResult(url, t.replace(/\n/g, '').replace(/=*$/g, ''), 'Base64url: ' + bin.length + ' bytes'); 239 + // check conversion from base64url to base64 240 + let pretty = Base64.pretty(url); 241 + this.checkResult(pretty, t, 'Base64pretty: ' + bin.length + ' bytes'); 242 + let std = new Stream(bin, 0).b64Dump(0, bin.length, 'std'); 243 + // check direct base64 encoding 244 + this.checkResult(std, t.replace(/\n/g, ''), 'Base64: ' + bin.length + ' bytes'); 245 + }, [ 246 + 'AA==', 247 + 'ABA=', 248 + 'ABCD', 249 + 'ABCDEA==', 250 + 'ABCDEFE=', 251 + 'ABCDEFGH', 252 + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQR\nSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456w==', 253 + ])); 254 + 255 + for (const t of tests) 256 + t.checkAll(); 257 + 258 + console.log(stats.run + ' tested, ' + stats.error + ' errors.'); 259 + process.exit(stats.error ? 1 : 0);
+32
testDefs.js
··· 1 + #!/usr/bin/env node 2 + 3 + import { promises as fs } from 'node:fs'; 4 + import { ASN1 } from './asn1.js'; 5 + import { Base64 } from './base64.js'; 6 + import { Defs } from './defs.js'; 7 + 8 + const tot = []; 9 + for await (const file of await fs.opendir('examples')) { 10 + let content = await fs.readFile('examples/' + file.name); 11 + try { 12 + try { // try PEM first 13 + content = Base64.unarmor(content); 14 + } catch (ignore) { // try DER/BER then 15 + } 16 + let result = ASN1.decode(content); 17 + content = null; 18 + const types = Defs.commonTypes 19 + .map(type => { 20 + const stats = Defs.match(result, type); 21 + return { type, match: stats.recognized / stats.total }; 22 + }) 23 + .sort((a, b) => b.match - a.match); 24 + tot.push([ types[0].match, file.name, types[0].type.description ]); 25 + } catch (e) { 26 + tot.push([ 0, file.name, e.message ]); 27 + } 28 + } 29 + for (const f of tot) 30 + console.log(f[0].toFixed(3) + '\t' + f[1] + '\t' + f[2]); 31 + const avg = tot.map(f => f[0]).reduce((sum, val) => sum + val) / tot.length; 32 + console.log('\x1B[1m\x1B[32m' + (avg * 100).toFixed(3) + '\x1B[39m\x1B[22m%\tAVERAGE');
+37
theme.js
··· 1 + // set dark theme depending on OS settings 2 + function setTheme(theme) { 3 + if (theme == 'os') { 4 + let prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)'); 5 + if (prefersDarkScheme.matches) { 6 + theme = 'dark'; 7 + } else { 8 + theme = 'light'; 9 + } 10 + } 11 + document.documentElement.style['color-scheme'] = theme; 12 + document.querySelector('html').setAttribute('data-theme', theme); 13 + // set the theme-color for iOS devices 14 + let bgColor = getComputedStyle(document.documentElement).getPropertyValue('--main-bg-color'); 15 + let metaThemeColor = document.querySelector('meta[name=theme-color]'); 16 + metaThemeColor.setAttribute('content', bgColor); 17 + } 18 + // activate selected theme 19 + let theme = 'os'; 20 + const localStorageTheme = localStorage.getItem('theme'); 21 + if (localStorageTheme) { 22 + theme = localStorageTheme; 23 + } 24 + setTheme(theme); 25 + // add handler to theme selection element 26 + const selectTheme = document.getElementById('theme-select'); 27 + if (selectTheme) { 28 + selectTheme.addEventListener ('change', function () { 29 + localStorage.setItem('theme', selectTheme.value); 30 + setTheme(selectTheme.value); 31 + }); 32 + if (theme == 'light') { 33 + selectTheme.selectedIndex = 2; 34 + } else if (theme == 'dark') { 35 + selectTheme.selectedIndex = 1; 36 + } 37 + }
+1
tree-icon-dark.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" width="28" height="14"><circle cx="6.903" cy="7.102" r="5.165" style="fill:#000;fill-opacity:1;stroke:#555;stroke-width:1.03676;stroke-dasharray:none;stroke-opacity:1"/><circle cx="21.133" cy="7.029" r="5.165" style="fill:#000;fill-opacity:1;stroke:#555;stroke-width:1.03676;stroke-dasharray:none;stroke-opacity:1"/><path d="M17.908 7.071h6.783" style="opacity:1;fill:none;fill-opacity:1;stroke:#555;stroke-width:1.03676;stroke-dasharray:none;stroke-opacity:1"/><g style="fill:none;fill-opacity:1;stroke:#555;stroke-width:.518375;stroke-dasharray:none;stroke-opacity:1"><path d="M5.231 9.992h9.466" style="opacity:.992268;fill:none;fill-opacity:1;stroke:#555;stroke-width:1.44663;stroke-dasharray:none;stroke-opacity:1" transform="translate(-.289 -.083)scale(.71667)"/><path d="M10.006 5.242v9.465" style="opacity:1;fill:none;fill-opacity:1;stroke:#555;stroke-width:1.44663;stroke-dasharray:none;stroke-opacity:1" transform="translate(-.289 -.083)scale(.71667)"/></g></svg>
+1
tree-icon-light.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" width="28" height="14"><circle cx="6.936" cy="7.247" r="5.165" style="fill:silver;fill-opacity:1;stroke:#999;stroke-width:1.03676;stroke-dasharray:none;stroke-opacity:1"/><circle cx="21.166" cy="7.174" r="5.165" style="fill:silver;fill-opacity:1;stroke:#999;stroke-width:1.03676;stroke-dasharray:none;stroke-opacity:1"/><path d="M17.94 7.216h6.784" style="fill:none;fill-opacity:1;stroke:#999;stroke-width:1.03676;stroke-dasharray:none;stroke-opacity:1"/><g style="fill:none;fill-opacity:1;stroke:#999;stroke-width:.518375;stroke-dasharray:none;stroke-opacity:1"><path d="M5.231 9.992h9.466" style="opacity:.992268;fill:none;fill-opacity:1;stroke:#999;stroke-width:1.44663;stroke-dasharray:none;stroke-opacity:1" transform="translate(-.256 .062)scale(.71667)"/><path d="M10.006 5.242v9.465" style="opacity:1;fill:none;fill-opacity:1;stroke:#999;stroke-width:1.44663;stroke-dasharray:none;stroke-opacity:1" transform="translate(-.256 .062)scale(.71667)"/></g></svg>
+1 -1
updateRFC.sh
··· 1 1 #/bin/sh 2 - RFCs="5280 5208 3369 3161 2986 4211 4210 8017" 2 + RFCs="5280 5208 3369 3161 2986 4211 4210 8017 4511" 3 3 downloadRFC() { 4 4 URL="https://www.ietf.org/rfc/rfc$1.txt" 5 5 if [ -x /usr/bin/fetch ]; then
+43
vite.config.js
··· 1 + import fs from 'node:fs'; 2 + import { defineConfig } from 'vite'; 3 + import { viteSingleFile } from 'vite-plugin-singlefile'; 4 + import pluginDom from 'vite-plugin-dom'; 5 + import { DomUtils } from 'htmlparser2'; 6 + 7 + const removeNodes = [ 'rowExamples' ]; 8 + 9 + const preventSVGEmit = () => { 10 + return { 11 + generateBundle(opts, bundle) { 12 + for (const key in bundle) 13 + if (key.endsWith('.svg')) 14 + delete bundle[key]; 15 + }, 16 + }; 17 + }; 18 + 19 + function massageSVG(str) { 20 + return str.replace(/["<>#]/g, (c) => { 21 + return '%' + c.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0'); 22 + }); 23 + } 24 + 25 + export default defineConfig({ 26 + plugins: [ 27 + preventSVGEmit(), 28 + pluginDom({ 29 + applyOnMode: true, // all modes 30 + handler: node => { 31 + if (removeNodes.includes(node.attribs.id)) 32 + DomUtils.removeElement(node); 33 + else if (node.name == 'link' && node.attribs.rel == 'icon') 34 + node.attribs.href = 'data:image/svg+xml,' + massageSVG(fs.readFileSync('favicon.svg', 'ascii').replace(/^([^<]+|<[^s]|<s[^v]|<sv[^g])+/, '').trim()); 35 + }, 36 + }), 37 + viteSingleFile(), 38 + ], 39 + build: { 40 + minify: false, 41 + cssMinify: false, 42 + }, 43 + });