iso-signatures 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,31 @@
1
+ export const INT_TAG: 2;
2
+ export const BITSTRING_TAG: 3;
3
+ export const OCTET_STRING_TAG: 4;
4
+ export const NULL_TAG: 5;
5
+ export const OBJECT_TAG: 6;
6
+ export const SEQUENCE_TAG: 48;
7
+ export const UNUSED_BIT_PAD: 0;
8
+ export function encodeDERLength(length: number): Uint8Array;
9
+ export function readDERLength(bytes: Uint8Array, offset?: number): {
10
+ number: number;
11
+ consumed: number;
12
+ };
13
+ export function skip(input: Uint8Array, expectedTag: number, position: number): number;
14
+ export function into(input: Uint8Array, expectedTag: number, offset: number): {
15
+ position: number;
16
+ length: number;
17
+ };
18
+ export function encodeBitString(input: Uint8Array): Uint8Array;
19
+ export function encodeOctetString(input: Uint8Array): Uint8Array;
20
+ export function encodeSequence(sequence: Uint8Array[]): Uint8Array;
21
+ export function readSequence(bytes: Uint8Array, offset?: number): Uint8Array;
22
+ export function encodeInt(input: Uint8Array): Uint8Array;
23
+ export function enterSequence(bytes: Uint8Array, offset?: number): number;
24
+ export function skipSequence(bytes: Uint8Array, offset?: number): number;
25
+ export function skipInt(bytes: Uint8Array, offset?: number): number;
26
+ export function readBitString(bytes: Uint8Array, offset?: number): Uint8Array;
27
+ export function readInt(bytes: Uint8Array, byteOffset?: number): Uint8Array;
28
+ export function readOctetString(bytes: Uint8Array, offset?: number): Uint8Array;
29
+ export function readSequenceWith(readers: [Reader, ...Reader[]], source: Uint8Array, byteOffset?: number): Uint8Array[];
30
+ export type Reader = (bytes: Uint8Array, offset: number) => Uint8Array;
31
+ //# sourceMappingURL=asn1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asn1.d.ts","sourceRoot":"","sources":["../../src/asn1.js"],"names":[],"mappings":"AAIA,wBAA2B;AAC3B,8BAAiC;AACjC,iCAAoC;AACpC,yBAA4B;AAC5B,2BAA8B;AAC9B,8BAAgC;AAEhC,+BAAkC;AAM3B,wCAHI,MAAM,GACJ,UAAU,CAetB;AAOM,qCAJI,UAAU,WACV,MAAM,GACJ;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAsB9C;AAQM,4BALI,UAAU,eACV,MAAM,YACN,MAAM,GACJ,MAAM,CAKlB;AAQM,4BALI,UAAU,eACV,MAAM,UACN,MAAM;cACQ,MAAM;YAAU,MAAM;EAmB9C;AAKM,uCAFI,UAAU,cA8BpB;AAKM,yCAFI,UAAU,cAqBpB;AAKM,yCAFI,UAAU,EAAE,cAgCtB;AAMM,oCAHI,UAAU,WACV,MAAM,cAMhB;AAKM,iCAFI,UAAU,cAkCpB;AAQM,qCALI,UAAU,WACV,MAAM,GACJ,MAAM,CAIyB;AAOrC,oCAJI,UAAU,WACV,MAAM,GACJ,MAAM,CAGgB;AAO5B,+BAJI,UAAU,WACV,MAAM,GACJ,MAAM,CAEuD;AAOnE,qCAJI,UAAU,WACV,MAAM,GACJ,UAAU,CAiBtB;AAOM,+BAJI,UAAU,eACV,MAAM,GACJ,UAAU,CAgBtB;AAOM,uCAJI,UAAU,WACV,MAAM,GACJ,UAAU,CAMtB;AAQM,0CAJI,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,UACrB,UAAU,eACV,MAAM,gBAYhB;6BAfmB,UAAU,UAAS,MAAM,KAAK,UAAU"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.js"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ export namespace spki {
2
+ export { encode };
3
+ export { decode };
4
+ }
5
+ /**
6
+ * @param {Uint8Array} key
7
+ */
8
+ declare function encode(key: Uint8Array): Uint8Array;
9
+ /**
10
+ * @param {Uint8Array} info
11
+ */
12
+ declare function decode(info: Uint8Array): Uint8Array;
13
+ export {};
14
+ //# sourceMappingURL=spki.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spki.d.ts","sourceRoot":"","sources":["../../src/spki.js"],"names":[],"mappings":";;;;AAgBA;;GAEG;AACH,6BAFW,UAAU,cAIpB;AAED;;GAEG;AACH,8BAFW,UAAU,cAUpB"}
@@ -0,0 +1,63 @@
1
+ import type { DIDKey } from 'iso-did/key';
2
+ import type { SignatureAlgorithm, KeyType } from 'iso-did/types';
3
+ export interface ISigner<Export extends CryptoKeyPair | string> {
4
+ /**
5
+ * JWT signing algorithm
6
+ */
7
+ alg: SignatureAlgorithm;
8
+ /**
9
+ * Keypair type
10
+ */
11
+ type: KeyType;
12
+ /**
13
+ * Multicodec identifier for the private key
14
+ */
15
+ code?: number;
16
+ did: DIDKey;
17
+ /**
18
+ * Sign a message
19
+ */
20
+ sign: (message: Uint8Array) => Promise<Uint8Array>;
21
+ export: () => Export;
22
+ }
23
+ export interface VerifyInput {
24
+ signature: Uint8Array;
25
+ message: Uint8Array;
26
+ publicKey: Uint8Array;
27
+ }
28
+ export type Verify = (input: VerifyInput) => Promise<boolean>;
29
+ export type Verifier<T extends SignatureAlgorithm> = Record<T, Verify>;
30
+ export type VerifierRegistry<T extends SignatureAlgorithm> = Partial<Verifier<T>>;
31
+ export interface ResolverVerifyInput extends VerifyInput {
32
+ alg: SignatureAlgorithm;
33
+ }
34
+ export type Cache = (parsed: VerifyInput, verify: Verify) => Promise<boolean>;
35
+ export interface IResolver {
36
+ verify: (input: ResolverVerifyInput) => Promise<boolean>;
37
+ }
38
+ export interface ResolverOptions {
39
+ cache?: Cache | boolean | undefined;
40
+ }
41
+ export interface PublicKeyJwk {
42
+ kty: string;
43
+ crv: string;
44
+ x: string;
45
+ y: string;
46
+ }
47
+ export interface PublicKeyRSAJwk {
48
+ kty: string;
49
+ n: string;
50
+ e: string;
51
+ }
52
+ export interface PrivateKeyRSAJwk extends PublicKeyRSAJwk {
53
+ d: string;
54
+ p: string;
55
+ q: string;
56
+ dp: string;
57
+ dq: string;
58
+ qi: string;
59
+ }
60
+ export type PrivateKeyJwk = PublicKeyJwk & {
61
+ d: string;
62
+ };
63
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEhE,MAAM,WAAW,OAAO,CAAC,MAAM,SAAS,aAAa,GAAG,MAAM;IAC5D;;OAEG;IACH,GAAG,EAAE,kBAAkB,CAAA;IACvB;;OAEG;IACH,IAAI,EAAE,OAAO,CAAA;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;IAElD,MAAM,EAAE,MAAM,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,UAAU,CAAA;IACrB,OAAO,EAAE,UAAU,CAAA;IACnB,SAAS,EAAE,UAAU,CAAA;CACtB;AACD,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE7D,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,kBAAkB,IAAI,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;AAEtE,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,kBAAkB,IAAI,OAAO,CAClE,QAAQ,CAAC,CAAC,CAAC,CACZ,CAAA;AAED,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACtD,GAAG,EAAE,kBAAkB,CAAA;CACxB;AACD,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE7E,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACzD;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG;IAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Create web crypto params for ECDSA.
3
+ *
4
+ * @param {import("iso-did/types").SignatureAlgorithm} alg
5
+ * @returns {{name: 'ECDSA', namedCurve: 'P-256' | 'P-384' | 'P-521', hash: 'SHA-256' | 'SHA-384' | 'SHA-512'}}
6
+ */
7
+ export function createEcdsaParams(alg: import("iso-did/types").SignatureAlgorithm): {
8
+ name: 'ECDSA';
9
+ namedCurve: 'P-256' | 'P-384' | 'P-521';
10
+ hash: 'SHA-256' | 'SHA-384' | 'SHA-512';
11
+ };
12
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,uCAHW,OAAO,eAAe,EAAE,kBAAkB,GACxC;IAAC,MAAM,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;CAAC,CA8B7G"}
package/package.json ADDED
@@ -0,0 +1,138 @@
1
+ {
2
+ "name": "iso-signatures",
3
+ "version": "0.0.1",
4
+ "description": "Signatures tooling.",
5
+ "author": "Hugo Dias <hugomrdias@gmail.com> (hugodias.me)",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "url": "hugomrdias/iso-repo",
9
+ "directory": "packages/iso-signatures"
10
+ },
11
+ "homepage": "https://github.com/hugomrdias/iso-repo/tree/main/packages/iso-signatures",
12
+ "keywords": [
13
+ "elliptic",
14
+ "curve",
15
+ "cryptography",
16
+ "edwards",
17
+ "p256",
18
+ "p384",
19
+ "p521",
20
+ "secp256r1",
21
+ "secp256k1",
22
+ "ed25519",
23
+ "ecdsa",
24
+ "eddsa",
25
+ "rsa",
26
+ "signatures"
27
+ ],
28
+ "type": "module",
29
+ "main": "src/index.js",
30
+ "types": "dist/src/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/src/index.d.ts",
34
+ "import": "./src/index.js"
35
+ },
36
+ "./signers/ecdsa": {
37
+ "types": "./dist/src/signers/ecdsa.d.ts",
38
+ "import": "./src/signers/ecdsa.js"
39
+ },
40
+ "./signers/eddsa": {
41
+ "types": "./dist/src/signers/eddsa.d.ts",
42
+ "import": "./src/signers/eddsa.js"
43
+ },
44
+ "./signers/rsa-old": {
45
+ "types": "./dist/src/signers/rsa-old.d.ts",
46
+ "import": "./src/signers/rsa-old.js"
47
+ },
48
+ "./signers/rsa": {
49
+ "types": "./dist/src/signers/rsa.d.ts",
50
+ "import": "./src/signers/rsa.js"
51
+ },
52
+ "./verifiers/ecdsa": {
53
+ "types": "./dist/src/verifiers/ecdsa.d.ts",
54
+ "import": "./src/verifiers/ecdsa.js"
55
+ },
56
+ "./verifiers/eddsa": {
57
+ "types": "./dist/src/verifiers/eddsa.d.ts",
58
+ "import": "./src/verifiers/eddsa.js"
59
+ },
60
+ "./verifiers/rsa-old": {
61
+ "types": "./dist/src/verifiers/rsa-old.d.ts",
62
+ "import": "./src/verifiers/rsa-old.js"
63
+ },
64
+ "./verifiers/rsa": {
65
+ "types": "./dist/src/verifiers/rsa.d.ts",
66
+ "import": "./src/verifiers/rsa.js"
67
+ },
68
+ "./verifiers/resolver": {
69
+ "types": "./dist/src/verifiers/resolver.d.ts",
70
+ "import": "./src/verifiers/resolver.js"
71
+ }
72
+ },
73
+ "typesVersions": {
74
+ "*": {
75
+ ".": [
76
+ "dist/src/index"
77
+ ],
78
+ "signers/*": [
79
+ "dist/src/signers/*"
80
+ ],
81
+ "verifiers/*": [
82
+ "dist/src/verifiers/*"
83
+ ]
84
+ }
85
+ },
86
+ "files": [
87
+ "src",
88
+ "dist/src/*.d.ts",
89
+ "dist/src/*.d.ts.map"
90
+ ],
91
+ "dependencies": {
92
+ "@noble/ed25519": "^2.0.0",
93
+ "iso-base": "^1.0.0",
94
+ "iso-did": "^1.3.0"
95
+ },
96
+ "devDependencies": {
97
+ "@types/assert": "^1.5.6",
98
+ "@types/mocha": "^10.0.1",
99
+ "@types/node": "^20.3.1",
100
+ "assert": "^2.0.0",
101
+ "hd-scripts": "^7.0.0",
102
+ "mocha": "^10.2.0",
103
+ "playwright-test": "^9.2.0",
104
+ "type-fest": "^3.12.0",
105
+ "typescript": "5.1.3"
106
+ },
107
+ "eslintConfig": {
108
+ "extends": [
109
+ "../../node_modules/hd-scripts/eslint/index.js"
110
+ ],
111
+ "parserOptions": {
112
+ "project": "./tsconfig.json"
113
+ },
114
+ "env": {
115
+ "mocha": true
116
+ },
117
+ "ignorePatterns": [
118
+ "dist"
119
+ ]
120
+ },
121
+ "depcheck": {
122
+ "specials": [
123
+ "bin"
124
+ ],
125
+ "ignores": [
126
+ "@types/*",
127
+ "hd-scripts",
128
+ "assert",
129
+ "type-fest"
130
+ ]
131
+ },
132
+ "scripts": {
133
+ "lint": "tsc --build && eslint '**/*.{js,ts}' && prettier --check '**/*.{js,ts,yml,json}' --ignore-path ../../.gitignore",
134
+ "test": "tsc --build && pnpm run test:node && pnpm run test:browser",
135
+ "test:node": "mocha 'test/**/!(*.browser).test.js'",
136
+ "test:browser": "playwright-test 'test/**/!(*.node).test.js'"
137
+ }
138
+ }
package/readme.md ADDED
@@ -0,0 +1,59 @@
1
+ # iso-signatures [![NPM Version](https://img.shields.io/npm/v/iso-signatures.svg)](https://www.npmjs.com/package/iso-signatures) [![License](https://img.shields.io/npm/l/iso-signatures.svg)](https://github.com/hugomrdias/iso-repo/blob/main/license) [![iso-did](https://github.com/hugomrdias/iso-repo/actions/workflows/iso-signatures.yml/badge.svg)](https://github.com/hugomrdias/iso-repo/actions/workflows/iso-signatures.yml)
2
+
3
+ > Isomorphic signatures tooling
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm install iso-signatures
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```js
14
+ import { EdDSASigner } from 'iso-signatures/signers/eddsa'
15
+ import * as EdDSA from 'iso-signatures/verifiers/eddsa'
16
+
17
+ const message = new TextEncoder().encode('hello world')
18
+ const resolver = new Resolver({
19
+ ...EdDSA.verifier,
20
+ })
21
+ const signer = await EdDSASigner.generate()
22
+ const signature = await signer.sign(message)
23
+ const verified = await resolver.verify({
24
+ signature,
25
+ message,
26
+ ...signer,
27
+ })
28
+ ```
29
+
30
+ ```js
31
+ import { EdDSASigner } from 'iso-signatures/signers/eddsa'
32
+ import * as EdDSA from 'iso-signatures/verifiers/eddsa'
33
+ import * as ECDSA from 'iso-signatures/verifiers/ecdsa'
34
+ import * as RSA from 'iso-signatures/verifiers/rsa'
35
+
36
+ const message = new TextEncoder().encode('hello world')
37
+ const resolver = new Resolver(
38
+ {
39
+ ...ECDSA.verifier,
40
+ ...EdDSA.verifier,
41
+ },
42
+ { cache: true }
43
+ )
44
+ const signer = await EdDSASigner.generate()
45
+ const signature = await signer.sign(message)
46
+ const verified = await resolver.verify({
47
+ signature,
48
+ message,
49
+ ...signer.did, // Signer and DID both have `alg` property that the resolver uses to find the correct verifier
50
+ })
51
+ ```
52
+
53
+ ## Docs
54
+
55
+ Check <https://hugomrdias.github.io/iso-repo/modules/iso_signatures.html>
56
+
57
+ ## License
58
+
59
+ MIT © [Hugo Dias](http://hugodias.me)
package/src/asn1.js ADDED
@@ -0,0 +1,329 @@
1
+ /**
2
+ * ASN1 Tags as per https://luca.ntop.org/Teaching/Appunti/asn1.html
3
+ */
4
+ const TAG_SIZE = 1
5
+ export const INT_TAG = 0x02
6
+ export const BITSTRING_TAG = 0x03
7
+ export const OCTET_STRING_TAG = 0x04
8
+ export const NULL_TAG = 0x05
9
+ export const OBJECT_TAG = 0x06
10
+ export const SEQUENCE_TAG = 0x30
11
+
12
+ export const UNUSED_BIT_PAD = 0x00
13
+
14
+ /**
15
+ * @param {number} length
16
+ * @returns {Uint8Array}
17
+ */
18
+ export const encodeDERLength = (length) => {
19
+ if (length <= 127) {
20
+ return new Uint8Array([length])
21
+ }
22
+
23
+ /** @type {number[]} */
24
+ const octets = []
25
+ while (length !== 0) {
26
+ octets.push(length & 0xff)
27
+ length = length >>> 8
28
+ }
29
+ octets.reverse()
30
+ return new Uint8Array([0x80 | (octets.length & 0xff), ...octets])
31
+ }
32
+
33
+ /**
34
+ * @param {Uint8Array} bytes
35
+ * @param {number} offset
36
+ * @returns {{number: number, consumed: number}}
37
+ */
38
+ export const readDERLength = (bytes, offset = 0) => {
39
+ if ((bytes[offset] & 0x80) === 0) {
40
+ return { number: bytes[offset], consumed: 1 }
41
+ }
42
+
43
+ const numberBytes = bytes[offset] & 0x7f
44
+ /* c8 ignore next 5 */
45
+ if (bytes.length < numberBytes + 1) {
46
+ throw new Error(
47
+ `ASN parsing error: Too few bytes. Expected encoded length's length to be at least ${numberBytes}`
48
+ )
49
+ }
50
+
51
+ let length = 0
52
+ for (let i = 0; i < numberBytes; i++) {
53
+ length = length << 8
54
+ length = length | bytes[offset + i + 1]
55
+ }
56
+
57
+ return { number: length, consumed: numberBytes + 1 }
58
+ }
59
+
60
+ /**
61
+ * @param {Uint8Array} input
62
+ * @param {number} expectedTag
63
+ * @param {number} position
64
+ * @returns {number}
65
+ */
66
+ export const skip = (input, expectedTag, position) => {
67
+ const parsed = into(input, expectedTag, position)
68
+ return parsed.position + parsed.length
69
+ }
70
+
71
+ /**
72
+ * @param {Uint8Array} input
73
+ * @param {number} expectedTag
74
+ * @param {number} offset
75
+ * @returns {{ position: number, length: number }}
76
+ */
77
+ export const into = (input, expectedTag, offset) => {
78
+ const actualTag = input[offset]
79
+ /* c8 ignore next 7 */
80
+ if (actualTag !== expectedTag) {
81
+ throw new Error(
82
+ `ASN parsing error: Expected tag 0x${expectedTag.toString(
83
+ 16
84
+ )} at position ${offset}, but got 0x${actualTag.toString(16)}.`
85
+ )
86
+ }
87
+
88
+ // length
89
+ const length = readDERLength(input, offset + TAG_SIZE)
90
+ const position = offset + TAG_SIZE + length.consumed
91
+
92
+ // content
93
+ return { position, length: length.number }
94
+ }
95
+
96
+ /**
97
+ * @param {Uint8Array} input
98
+ */
99
+ export const encodeBitString = (input) => {
100
+ // encode input length + 1 for unused bit pad
101
+ const length = encodeDERLength(input.byteLength + 1)
102
+ // allocate a buffer of desired size
103
+ const bytes = new Uint8Array(
104
+ TAG_SIZE + // ASN_BITSTRING_TAG
105
+ length.byteLength +
106
+ 1 + // amount of unused bits at the end of our bitstring
107
+ input.byteLength
108
+ )
109
+
110
+ let byteOffset = 0
111
+ // write bytestring tag
112
+ bytes[byteOffset] = BITSTRING_TAG
113
+ byteOffset += TAG_SIZE
114
+
115
+ // write length of the bytestring
116
+ bytes.set(length, byteOffset)
117
+ byteOffset += length.byteLength
118
+
119
+ // write unused bits at the end of our bitstring
120
+ bytes[byteOffset] = UNUSED_BIT_PAD
121
+ byteOffset += 1
122
+
123
+ // write actual data into bitstring
124
+ bytes.set(input, byteOffset)
125
+
126
+ return bytes
127
+ }
128
+
129
+ /**
130
+ * @param {Uint8Array} input
131
+ */
132
+ export const encodeOctetString = (input) => {
133
+ // encode input length
134
+ const length = encodeDERLength(input.byteLength)
135
+ // allocate a buffer of desired size
136
+ const bytes = new Uint8Array(TAG_SIZE + length.byteLength + input.byteLength)
137
+
138
+ let byteOffset = 0
139
+ // write octet string tag
140
+ bytes[byteOffset] = OCTET_STRING_TAG
141
+ byteOffset += TAG_SIZE
142
+
143
+ // write octet string length
144
+ bytes.set(length, byteOffset)
145
+ byteOffset += length.byteLength
146
+
147
+ // write actual data into bitstring
148
+ bytes.set(input, byteOffset)
149
+
150
+ return bytes
151
+ }
152
+
153
+ /**
154
+ * @param {Uint8Array[]} sequence
155
+ */
156
+ export const encodeSequence = (sequence) => {
157
+ // calculate bytelength for all the parts
158
+ let byteLength = 0
159
+ for (const item of sequence) {
160
+ byteLength += item.byteLength
161
+ }
162
+
163
+ // encode sequence byte length
164
+ const length = encodeDERLength(byteLength)
165
+
166
+ // allocate the buffer to write sequence into
167
+ const bytes = new Uint8Array(TAG_SIZE + length.byteLength + byteLength)
168
+
169
+ let byteOffset = 0
170
+
171
+ // write the sequence tag
172
+ bytes[byteOffset] = SEQUENCE_TAG
173
+ byteOffset += TAG_SIZE
174
+
175
+ // write sequence length
176
+ bytes.set(length, byteOffset)
177
+ byteOffset += length.byteLength
178
+
179
+ // write each item in the sequence
180
+ for (const item of sequence) {
181
+ bytes.set(item, byteOffset)
182
+ byteOffset += item.byteLength
183
+ }
184
+
185
+ return bytes
186
+ }
187
+
188
+ /**
189
+ * @param {Uint8Array} bytes
190
+ * @param {number} offset
191
+ */
192
+ export const readSequence = (bytes, offset = 0) => {
193
+ const { position, length } = into(bytes, SEQUENCE_TAG, offset)
194
+
195
+ return new Uint8Array(bytes.buffer, bytes.byteOffset + position, length)
196
+ }
197
+
198
+ /**
199
+ * @param {Uint8Array} input
200
+ */
201
+ export const encodeInt = (input) => {
202
+ const extra = input.byteLength === 0 || input[0] & 0x80 ? 1 : 0
203
+
204
+ // encode input length
205
+ const length = encodeDERLength(input.byteLength + extra)
206
+ // allocate a buffer of desired size
207
+ const bytes = new Uint8Array(
208
+ TAG_SIZE + // INT_TAG
209
+ length.byteLength +
210
+ input.byteLength +
211
+ extra
212
+ )
213
+
214
+ let byteOffset = 0
215
+ // write octet string tag
216
+ bytes[byteOffset] = INT_TAG
217
+ byteOffset += TAG_SIZE
218
+
219
+ // write int length
220
+ bytes.set(length, byteOffset)
221
+ byteOffset += length.byteLength
222
+
223
+ // add 0 if the most-significant bit is set
224
+ if (extra > 0) {
225
+ bytes[byteOffset] = UNUSED_BIT_PAD
226
+ byteOffset += extra
227
+ }
228
+
229
+ // write actual data into bitstring
230
+ bytes.set(input, byteOffset)
231
+
232
+ return bytes
233
+ }
234
+
235
+ /**
236
+ * @param {Uint8Array} bytes
237
+ * @param {number} offset
238
+ * @returns {number}
239
+ */
240
+
241
+ export const enterSequence = (bytes, offset = 0) =>
242
+ into(bytes, SEQUENCE_TAG, offset).position
243
+
244
+ /**
245
+ * @param {Uint8Array} bytes
246
+ * @param {number} offset
247
+ * @returns {number}
248
+ */
249
+ export const skipSequence = (bytes, offset = 0) =>
250
+ skip(bytes, SEQUENCE_TAG, offset)
251
+
252
+ /**
253
+ * @param {Uint8Array} bytes
254
+ * @param {number} offset
255
+ * @returns {number}
256
+ */
257
+ export const skipInt = (bytes, offset = 0) => skip(bytes, INT_TAG, offset)
258
+
259
+ /**
260
+ * @param {Uint8Array} bytes
261
+ * @param {number} offset
262
+ * @returns {Uint8Array}
263
+ */
264
+ export const readBitString = (bytes, offset = 0) => {
265
+ const { position, length } = into(bytes, BITSTRING_TAG, offset)
266
+ const tag = bytes[position]
267
+ /* c8 ignore next 5 */
268
+ if (tag !== UNUSED_BIT_PAD) {
269
+ throw new Error(
270
+ `Can not read bitstring, expected length to be multiple of 8, but got ${tag} unused bits in last byte.`
271
+ )
272
+ }
273
+
274
+ return new Uint8Array(
275
+ bytes.buffer,
276
+ bytes.byteOffset + position + 1,
277
+ length - 1
278
+ )
279
+ }
280
+
281
+ /**
282
+ * @param {Uint8Array} bytes
283
+ * @param {number} byteOffset
284
+ * @returns {Uint8Array}
285
+ */
286
+ export const readInt = (bytes, byteOffset = 0) => {
287
+ const { position, length } = into(bytes, INT_TAG, byteOffset)
288
+ let delta = 0
289
+
290
+ // drop leading 0s
291
+ while (bytes[position + delta] === 0) {
292
+ delta++
293
+ }
294
+
295
+ return new Uint8Array(
296
+ bytes.buffer,
297
+ bytes.byteOffset + position + delta,
298
+ length - delta
299
+ )
300
+ }
301
+
302
+ /**
303
+ * @param {Uint8Array} bytes
304
+ * @param {number} offset
305
+ * @returns {Uint8Array}
306
+ */
307
+ export const readOctetString = (bytes, offset = 0) => {
308
+ const { position, length } = into(bytes, OCTET_STRING_TAG, offset)
309
+
310
+ return new Uint8Array(bytes.buffer, bytes.byteOffset + position, length)
311
+ }
312
+
313
+ /**
314
+ * @typedef {(bytes:Uint8Array, offset:number) => Uint8Array} Reader
315
+ * @param {[Reader, ...Reader[]]} readers
316
+ * @param {Uint8Array} source
317
+ * @param {number} byteOffset
318
+ */
319
+ export const readSequenceWith = (readers, source, byteOffset = 0) => {
320
+ const results = []
321
+ const sequence = readSequence(source, byteOffset)
322
+ let offset = 0
323
+ for (const read of readers) {
324
+ const chunk = read(sequence, offset)
325
+ results.push(chunk)
326
+ offset = chunk.byteOffset + chunk.byteLength - sequence.byteOffset
327
+ }
328
+ return results
329
+ }
package/src/index.js ADDED
@@ -0,0 +1 @@
1
+ throw new Error('Incorrect "iso-signatures" usage. Import submodules instead')