@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 +1 -1
- package/package.json +10 -3
- package/src/digitalsealv3.js +12 -0
- package/src/digitalsealv4.js +12 -0
- package/src/index.js +1 -1
- package/src/mrvadocumentwithvds3.js +11 -0
- package/src/mrvadocumentwithvds4.js +11 -0
- package/src/mrvbdocumentwithvds3.js +11 -0
- package/src/mrvbdocumentwithvds4.js +11 -0
- package/src/td1documentwithvds3.js +11 -0
- package/src/td1documentwithvds4.js +11 -0
- package/src/td2documentwithvds3.js +11 -0
- package/src/td2documentwithvds4.js +11 -0
- package/src/td3documentwithvds3.js +11 -0
- package/src/td3documentwithvds4.js +11 -0
- package/src/utilities/get-hash.js +22 -0
- package/tests/models/digitalsealv4.test.js +11 -2
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
|
-
[](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.
|
|
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": [
|
|
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
|
-
|
package/src/digitalsealv3.js
CHANGED
|
@@ -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
|
|
package/src/digitalsealv4.js
CHANGED
|
@@ -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/
|
|
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
|
|