@gwydion-id/icao-9303-models 0.1.0 → 0.1.2

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.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  > A collection of exports to represent and use [ICAO Document 9303 machine-readable travel documents (MRTDs)][icao9303].
9
9
 
10
- [![REUSE status](https://api.reuse.software/badge/github.com/Gwydion-ID/icao-9303-models)](https://api.reuse.software/info/github.com/Gwydion-ID/icao-9303-models)
10
+ [![REUSE status](https://api.reuse.software/badge/github.com/gwydion-id/icao-9303-models)](https://api.reuse.software/info/github.com/gwydion-id/icao-9303-models)
11
11
 
12
12
  ## Provided exports
13
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gwydion-id/icao-9303-models",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "A collection of exports to represent and use ICAO Document 9303 machine-readable travel documents (MRTDs).",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -10,8 +10,15 @@
10
10
  "scripts": {
11
11
  "test": "node --test tests/**/*.test.js"
12
12
  },
13
- "keywords": ["icao", "icao9303", "mrz", "mrtd", "vds", "identity", "passport"],
13
+ "keywords": [
14
+ "icao",
15
+ "icao9303",
16
+ "mrz",
17
+ "mrtd",
18
+ "vds",
19
+ "identity",
20
+ "passport"
21
+ ],
14
22
  "author": "Don Geronimo",
15
23
  "license": "LGPL-3.0-or-later"
16
24
  }
17
-
@@ -9,6 +9,7 @@ import { VDS_SIGNATURE_MARKER } from "./utilities/vds-signature-marker.js";
9
9
  import { setSignatureZone } from "./utilities/set-signature-zone.js";
10
10
  import { VDS_VERSION_3 } from "./utilities/vds-version-3.js";
11
11
  import { IcaoDate } from "./utilities/icao-date.js";
12
+ import { getHash } from "./utilities/get-hash.js";
12
13
 
13
14
  /**
14
15
  * Stores properties and methods for ICAO 9303 visible digital seals (VDSs)
@@ -355,5 +356,16 @@ export class DigitalSealV3 {
355
356
  start = this.#setMessage(start, value);
356
357
  this.signatureData = setSignatureZone(start, value);
357
358
  }
359
+
360
+ /**
361
+ * Get a hash of the VDS for use in signing and verification operations.
362
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
363
+ * Web Crypto API supported hash function string.
364
+ * @returns { Promise<number[]> }
365
+ */
366
+ async getHash(algorithm = 'SHA-256') {
367
+ const output = await getHash(this.unsignedSeal, algorithm);
368
+ return output;
369
+ }
358
370
  }
359
371
 
@@ -11,6 +11,7 @@ import { lengthToDERLength } from "./utilities/length-to-der-length.js";
11
11
  import { derLengthToLength } from "./utilities/der-length-to-length.js";
12
12
  import { setSignatureZone } from "./utilities/set-signature-zone.js";
13
13
  import { IcaoDate } from "./utilities/icao-date.js";
14
+ import { getHash } from "./utilities/get-hash.js";
14
15
 
15
16
  /**
16
17
  * Stores properties and methods for ICAO 9303 visible digital seals (VDSs)
@@ -365,5 +366,16 @@ export class DigitalSealV4 {
365
366
  start = this.#setMessage(start, value);
366
367
  this.signatureData = setSignatureZone(start, value);
367
368
  }
369
+
370
+ /**
371
+ * Get a hash of the VDS for use in signing and verification operations.
372
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
373
+ * Web Crypto API supported hash function string.
374
+ * @returns { Promise<number[]> }
375
+ */
376
+ async getHash(algorithm = 'SHA-256') {
377
+ const output = await getHash(this.unsignedSeal, algorithm);
378
+ return output;
379
+ }
368
380
  }
369
381
 
package/src/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  // Utility exports
5
5
  export { NATIONALITY_CODES } from './utilities/nationality-codes.js';
6
6
  export { IcaoDate } from './utilities/icao-date.js';
7
- export { dateToBytes } from './utilities/dates-to-bytes.js';
7
+ export { dateToBytes } from './utilities/date-to-bytes.js';
8
8
  export { bytesToDate } from './utilities/bytes-to-date.js';
9
9
  export { c40Decode } from './utilities/c40-decode.js';
10
10
  export { c40Encode } from './utilities/c40-encode.js';
@@ -555,5 +555,16 @@ export class MRVADocumentWithVDS3 {
555
555
  * @param { number[] } value
556
556
  */
557
557
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
558
+
559
+ /**
560
+ * Get a hash of the VDS for use in signing and verification operations.
561
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
562
+ * Web Crypto API supported hash function string.
563
+ * @returns { Promise<number[]> }
564
+ */
565
+ async getHash(algorithm = 'SHA-256') {
566
+ const output = await this.#digitalseal.getHash(algorithm);
567
+ return output;
568
+ }
558
569
  }
559
570
 
@@ -555,5 +555,16 @@ export class MRVADocumentWithVDS4 {
555
555
  * @param { number[] } value
556
556
  */
557
557
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
558
+
559
+ /**
560
+ * Get a hash of the VDS for use in signing and verification operations.
561
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
562
+ * Web Crypto API supported hash function string.
563
+ * @returns { Promise<number[]> }
564
+ */
565
+ async getHash(algorithm = 'SHA-256') {
566
+ const output = await this.#digitalseal.getHash(algorithm);
567
+ return output;
568
+ }
558
569
  }
559
570
 
@@ -556,5 +556,16 @@ export class MRVBDocumentWithVDS3 {
556
556
  * @param { number[] } value
557
557
  */
558
558
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
559
+
560
+ /**
561
+ * Get a hash of the VDS for use in signing and verification operations.
562
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
563
+ * Web Crypto API supported hash function string.
564
+ * @returns { Promise<number[]> }
565
+ */
566
+ async getHash(algorithm = 'SHA-256') {
567
+ const output = await this.#digitalseal.getHash(algorithm);
568
+ return output;
569
+ }
559
570
  }
560
571
 
@@ -556,5 +556,16 @@ export class MRVBDocumentWithVDS4 {
556
556
  * @param { number[] } value
557
557
  */
558
558
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
559
+
560
+ /**
561
+ * Get a hash of the VDS for use in signing and verification operations.
562
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
563
+ * Web Crypto API supported hash function string.
564
+ * @returns { Promise<number[]> }
565
+ */
566
+ async getHash(algorithm = 'SHA-256') {
567
+ const output = await this.#digitalseal.getHash(algorithm);
568
+ return output;
569
+ }
559
570
  }
560
571
 
@@ -475,5 +475,16 @@ export class TD1DocumentWithVDS3 {
475
475
  * @param { number[] } value
476
476
  */
477
477
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
478
+
479
+ /**
480
+ * Get a hash of the VDS for use in signing and verification operations.
481
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
482
+ * Web Crypto API supported hash function string.
483
+ * @returns { Promise<number[]> }
484
+ */
485
+ async getHash(algorithm = 'SHA-256') {
486
+ const output = await this.#digitalseal.getHash(algorithm);
487
+ return output;
488
+ }
478
489
  }
479
490
 
@@ -475,5 +475,16 @@ export class TD1DocumentWithVDS4 {
475
475
  * @param { number[] } value
476
476
  */
477
477
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
478
+
479
+ /**
480
+ * Get a hash of the VDS for use in signing and verification operations.
481
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
482
+ * Web Crypto API supported hash function string.
483
+ * @returns { Promise<number[]> }
484
+ */
485
+ async getHash(algorithm = 'SHA-256') {
486
+ const output = await this.#digitalseal.getHash(algorithm);
487
+ return output;
488
+ }
478
489
  }
479
490
 
@@ -462,5 +462,16 @@ export class TD2DocumentWithVDS3 {
462
462
  * @param { number[] } value
463
463
  */
464
464
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
465
+
466
+ /**
467
+ * Get a hash of the VDS for use in signing and verification operations.
468
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
469
+ * Web Crypto API supported hash function string.
470
+ * @returns { Promise<number[]> }
471
+ */
472
+ async getHash(algorithm = 'SHA-256') {
473
+ const output = await this.#digitalseal.getHash(algorithm);
474
+ return output;
475
+ }
465
476
  }
466
477
 
@@ -462,5 +462,16 @@ export class TD2DocumentWithVDS4 {
462
462
  * @param { number[] } value
463
463
  */
464
464
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
465
+
466
+ /**
467
+ * Get a hash of the VDS for use in signing and verification operations.
468
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
469
+ * Web Crypto API supported hash function string.
470
+ * @returns { Promise<number[]> }
471
+ */
472
+ async getHash(algorithm = 'SHA-256') {
473
+ const output = await this.#digitalseal.getHash(algorithm);
474
+ return output;
475
+ }
465
476
  }
466
477
 
@@ -462,5 +462,16 @@ export class TD3DocumentWithVDS3 {
462
462
  * @param { number[] } value
463
463
  */
464
464
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
465
+
466
+ /**
467
+ * Get a hash of the VDS for use in signing and verification operations.
468
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
469
+ * Web Crypto API supported hash function string.
470
+ * @returns { Promise<number[]> }
471
+ */
472
+ async getHash(algorithm = 'SHA-256') {
473
+ const output = await this.#digitalseal.getHash(algorithm);
474
+ return output;
475
+ }
465
476
  }
466
477
 
@@ -462,5 +462,16 @@ export class TD3DocumentWithVDS4 {
462
462
  * @param { number[] } value
463
463
  */
464
464
  set signedSeal(value) { this.#digitalseal.signedSeal = value; }
465
+
466
+ /**
467
+ * Get a hash of the VDS for use in signing and verification operations.
468
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
469
+ * Web Crypto API supported hash function string.
470
+ * @returns { Promise<number[]> }
471
+ */
472
+ async getHash(algorithm = 'SHA-256') {
473
+ const output = await this.#digitalseal.getHash(algorithm);
474
+ return output;
475
+ }
465
476
  }
466
477
 
@@ -0,0 +1,22 @@
1
+ // SPDX-FileCopyrightText: 2026 Don Geronimo <https://sentamal.in>
2
+ // SPDX-License-Identifier: LGPL-3.0-or-later
3
+
4
+ /**
5
+ * Get a hash of the VDS for use in signing and verification operations.
6
+ *
7
+ * @async
8
+ * @param { number[] } byteArray
9
+ * @param { 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' } [algorithm = 'SHA-256'] - A
10
+ * Web Crypto API supported hash function string
11
+ * @returns { Promise<number[]> }
12
+ */
13
+ export async function getHash(byteArray, algorithm = 'SHA-256') {
14
+ const cryptoObject = globalThis.crypto;
15
+ if (!cryptoObject?.subtle) {
16
+ throw new Error('Web Crypto API is unavailable; ensure you are running in Node.js or in a Secure Context (HTTPS).');
17
+ }
18
+ const bytes = new Uint8Array(byteArray);
19
+ const hashBuffer = await cryptoObject.subtle.digest(algorithm, bytes);
20
+ return Array.from(new Uint8Array(hashBuffer));
21
+ }
22
+
@@ -19,11 +19,17 @@ const signedSeal = [ 0xdc, 0x03, 0xd9, 0xc5, 0xd9, 0xca, 0xc8, 0xa7, 0x3a, 0x99,
19
19
  0xfe, 0x15, 0xf6, 0x8d, 0xdd, 0x68, 0x18, 0xaf, 0x5a, 0x7b, 0xaf, 0x21, 0xca, 0x7c, 0xfc, 0x7e,
20
20
  0xb3, 0xbe ]
21
21
 
22
+ const sealHash = [ 0x02, 0x81, 0x9b, 0x0d, 0xd7, 0x08, 0x6f, 0x79,
23
+ 0x87, 0xf4, 0xb9, 0xa3, 0x23, 0xa3, 0x37, 0x58,
24
+ 0xea, 0xd3, 0xa5, 0x63, 0x87, 0x28, 0x98, 0xef,
25
+ 0x0c, 0x9a, 0xa1, 0xca, 0x20, 0xce, 0x7e, 0xa8 ]
26
+
22
27
  describe('Visible Digital Seal version 4', () => {
23
28
 
24
29
  describe('Import exemplary raw data from documentation [REF ICAO 9303 Part 7 Appendix E]', () => {
25
- it('should equal the values from exemplary VDS in Appendix E-2.', () => {
30
+ it('should equal the values from exemplary VDS in Appendix E-2.', async () => {
26
31
  const document = new DigitalSealV4({ signedSeal: signedSeal });
32
+ const hash = await document.getHash();
27
33
  assert.deepStrictEqual(document.authorityCode, 'UTO');
28
34
  assert.deepStrictEqual(document.identifierCode, 'UTTS');
29
35
  assert.deepStrictEqual(document.certReference,'5B');
@@ -37,11 +43,12 @@ describe('Visible Digital Seal version 4', () => {
37
43
  assert.deepStrictEqual(document.features.get(3), [ 2 ]);
38
44
  assert.deepStrictEqual(document.features.get(4), [ 0x5a, 0x00, 0x00 ]);
39
45
  assert.deepStrictEqual(c40Decode(document.features.get(5)), 'ABC424242');
46
+ assert.deepStrictEqual(hash, sealHash);
40
47
  });
41
48
  });
42
49
 
43
50
  describe('Use properties to reconstruct the exemplary raw data from documentation [REF ICAO 9303 Part 7 Appendix E]', () => {
44
- it('should equal the exemplary raw data from documentation in Appendix E-2.', () => {
51
+ it('should equal the exemplary raw data from documentation in Appendix E-2.', async () => {
45
52
  const document = new DigitalSealV4({
46
53
  authorityCode: 'UTO',
47
54
  identifierCode: 'UTTS',
@@ -59,7 +66,9 @@ describe('Visible Digital Seal version 4', () => {
59
66
  0x91, 0xbe, 0xb1, 0x19, 0x7b, 0xed, 0x97, 0xad, 0xf2, 0xff, 0x89, 0xe0, 0xa3, 0x44, 0x51, 0x2b,
60
67
  0x7b, 0x01, 0x36, 0xc4, 0x40, 0x50, 0xf1, 0x17, 0xe5, 0x07, 0xbc, 0x2a, 0x78, 0x2f, 0xfe, 0x15,
61
68
  0xf6, 0x8d, 0xdd, 0x68, 0x18, 0xaf, 0x5a, 0x7b, 0xaf, 0x21, 0xca, 0x7c, 0xfc, 0x7e, 0xb3, 0xbe ];
69
+ const hash = await document.getHash();
62
70
  assert.deepStrictEqual(document.signedSeal, signedSeal);
71
+ assert.deepStrictEqual(hash, sealHash);
63
72
  });
64
73
  });
65
74