qids-sdk 1.3.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/LICENSE +34 -0
- package/README.md +79 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.js +152 -0
- package/package.json +31 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
PROPRIETARY AND CONFIDENTIAL LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 QIDS. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
NOTICE: This software and associated documentation files (the "Software") are
|
|
6
|
+
the proprietary and confidential property of QIDS.
|
|
7
|
+
|
|
8
|
+
1. GRANT OF LICENSE
|
|
9
|
+
Subject to the terms and conditions of this Agreement, QIDS grants you a
|
|
10
|
+
limited, non-exclusive, non-transferable, revocable license to install and use
|
|
11
|
+
the SDK solely for the purpose of developing, testing, and integrating
|
|
12
|
+
client applications with authorized QIDS services and gateways.
|
|
13
|
+
|
|
14
|
+
2. RESTRICTIONS
|
|
15
|
+
You shall not, and shall not permit or authorize any third party to:
|
|
16
|
+
a. Decompile, disassemble, reverse-engineer, or attempt to derive the source
|
|
17
|
+
code, algorithms, or protocols of any portion of the Software.
|
|
18
|
+
b. Copy, modify, alter, translate, or create derivative works of the Software.
|
|
19
|
+
c. Sublicense, sell, resell, lease, distribute, or commercially exploit the
|
|
20
|
+
Software, in whole or in part, without an explicit commercial license agreement.
|
|
21
|
+
d. Circumvent, disable, or tamper with any security controls, licensing checks,
|
|
22
|
+
or telemetry systems embedded in the Software.
|
|
23
|
+
e. Remove, obscure, or alter any copyright, trademark, or proprietary notices.
|
|
24
|
+
|
|
25
|
+
3. INTELLECTUAL PROPERTY
|
|
26
|
+
All title, ownership rights, and intellectual property rights in and to the
|
|
27
|
+
Software remain exclusively with QIDS.
|
|
28
|
+
|
|
29
|
+
4. DISCLAIMER OF WARRANTIES
|
|
30
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
31
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
32
|
+
FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
33
|
+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER
|
|
34
|
+
LIABILITY ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# QIDS Node.js / TypeScript SDK
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/qids-sdk)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
**Official TypeScript & Node.js client SDK for Quantum Digital Signatures (QDS) & Information-Theoretic Security.**
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install qids-sdk
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
or via yarn / pnpm:
|
|
17
|
+
```bash
|
|
18
|
+
yarn add qids-sdk
|
|
19
|
+
pnpm add qids-sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quickstart
|
|
25
|
+
|
|
26
|
+
### 1. Initialize Client & Sign a Document
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { QIDSClient } from "qids-sdk";
|
|
30
|
+
|
|
31
|
+
// Initialize client for your node
|
|
32
|
+
const client = new QIDSClient({
|
|
33
|
+
nodeId: "bank_node_alpha",
|
|
34
|
+
// Optional: connect to carrier-grade ETSI GS QKD 014 Key Management Entity
|
|
35
|
+
// etsiKmsUrl: "https://qkd-kms.internal.network",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
async function main() {
|
|
39
|
+
const payload = "TRANSFER 1,000,000 USD TO ACCT-48910";
|
|
40
|
+
|
|
41
|
+
// 1. Sign document payload for designated verifiers
|
|
42
|
+
const signature = await client.sign(
|
|
43
|
+
"DOC-2026-98104",
|
|
44
|
+
payload,
|
|
45
|
+
["bank_node_beta"]
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
console.log(`Signed document: ${signature.documentId}`);
|
|
49
|
+
console.log(`Generated ${signature.signatureTags.length} recipient tag(s)`);
|
|
50
|
+
|
|
51
|
+
// 2. Designated recipient verifies signature
|
|
52
|
+
const verification = await client.verify(
|
|
53
|
+
signature.documentId,
|
|
54
|
+
payload,
|
|
55
|
+
"bank_node_alpha",
|
|
56
|
+
signature.signatureTags[0]
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
console.log(`Verification: ${verification.reason}`);
|
|
60
|
+
// Output: Verification: ACCEPTED
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
main().catch(console.error);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Features
|
|
69
|
+
|
|
70
|
+
- **Information-Theoretic Security**: Immunity against quantum computer attacks (Shor's algorithm).
|
|
71
|
+
- **Sub-Millisecond Verification**: Ultra-low latency deterministic verification pipeline.
|
|
72
|
+
- **ETSI GS QKD 014 Compliant**: Standardized REST integration for carrier-grade quantum hardware.
|
|
73
|
+
- **Zero Black-Box AI/ML**: Fully auditable, closed-form deterministic verification.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
Proprietary and Confidential. Copyright (c) 2026 QIDS. All Rights Reserved. See [LICENSE](LICENSE) for details.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QIDS TypeScript/Node.js SDK
|
|
3
|
+
* Enterprise client for Quantum Digital Signatures (QDS) & Post-Quantum Non-Repudiation.
|
|
4
|
+
*/
|
|
5
|
+
export interface ETSIKey {
|
|
6
|
+
keyId: string;
|
|
7
|
+
keyBytes: Uint8Array;
|
|
8
|
+
sizeBits: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ETSIStatus {
|
|
11
|
+
sourceKmeId: string;
|
|
12
|
+
destinationKmeId: string;
|
|
13
|
+
sourceSaeId: string;
|
|
14
|
+
destinationSaeId: string;
|
|
15
|
+
keySize: number;
|
|
16
|
+
storedKeyCount: number;
|
|
17
|
+
maxKeyCount: number;
|
|
18
|
+
}
|
|
19
|
+
export interface SignatureTag {
|
|
20
|
+
recipientSaeId: string;
|
|
21
|
+
hashTagHex: string;
|
|
22
|
+
tagLengthBits: number;
|
|
23
|
+
keyId: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SignResponse {
|
|
26
|
+
documentId: string;
|
|
27
|
+
documentHash: string;
|
|
28
|
+
signatureTags: SignatureTag[];
|
|
29
|
+
signedAtUtcMs: number;
|
|
30
|
+
algorithm: string;
|
|
31
|
+
}
|
|
32
|
+
export interface VerifyResponse {
|
|
33
|
+
documentId: string;
|
|
34
|
+
isValid: boolean;
|
|
35
|
+
observedErrorRate: number;
|
|
36
|
+
thresholdErrorRate: number;
|
|
37
|
+
bitMismatches: number;
|
|
38
|
+
reason: string;
|
|
39
|
+
}
|
|
40
|
+
export declare class ETSI014Client {
|
|
41
|
+
private baseUrl;
|
|
42
|
+
private sourceSaeId;
|
|
43
|
+
private destinationSaeId;
|
|
44
|
+
constructor(baseUrl: string, sourceSaeId: string, destinationSaeId: string);
|
|
45
|
+
getStatus(): Promise<ETSIStatus>;
|
|
46
|
+
getEncKeys(number?: number, size?: number): Promise<ETSIKey[]>;
|
|
47
|
+
getDecKeys(keyIds: string[]): Promise<ETSIKey[]>;
|
|
48
|
+
}
|
|
49
|
+
export interface QIDSClientConfig {
|
|
50
|
+
nodeId: string;
|
|
51
|
+
etsiKmsUrl?: string;
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
}
|
|
54
|
+
export declare class QIDSClient {
|
|
55
|
+
readonly nodeId: string;
|
|
56
|
+
readonly etsiKmsUrl?: string;
|
|
57
|
+
readonly timeoutMs: number;
|
|
58
|
+
constructor(config: QIDSClientConfig);
|
|
59
|
+
getEtsiClient(peerSaeId: string): ETSI014Client;
|
|
60
|
+
sign(documentId: string, payload: Uint8Array | string, recipientIds: string[]): Promise<SignResponse>;
|
|
61
|
+
verify(documentId: string, payload: Uint8Array | string, senderId: string, signatureTag: SignatureTag): Promise<VerifyResponse>;
|
|
62
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* QIDS TypeScript/Node.js SDK
|
|
4
|
+
* Enterprise client for Quantum Digital Signatures (QDS) & Post-Quantum Non-Repudiation.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.QIDSClient = exports.ETSI014Client = void 0;
|
|
8
|
+
const node_crypto_1 = require("node:crypto");
|
|
9
|
+
class ETSI014Client {
|
|
10
|
+
baseUrl;
|
|
11
|
+
sourceSaeId;
|
|
12
|
+
destinationSaeId;
|
|
13
|
+
constructor(baseUrl, sourceSaeId, destinationSaeId) {
|
|
14
|
+
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
15
|
+
this.sourceSaeId = sourceSaeId;
|
|
16
|
+
this.destinationSaeId = destinationSaeId;
|
|
17
|
+
}
|
|
18
|
+
async getStatus() {
|
|
19
|
+
const url = `${this.baseUrl}/api/v1/keys/${this.destinationSaeId}/status`;
|
|
20
|
+
const res = await fetch(url, {
|
|
21
|
+
method: "GET",
|
|
22
|
+
headers: { Accept: "application/json" },
|
|
23
|
+
});
|
|
24
|
+
if (!res.ok) {
|
|
25
|
+
throw new Error(`ETSI KMS status query failed: HTTP ${res.status}`);
|
|
26
|
+
}
|
|
27
|
+
const data = await res.json();
|
|
28
|
+
return {
|
|
29
|
+
sourceKmeId: data.source_KME_ID ?? "",
|
|
30
|
+
destinationKmeId: data.destination_KME_ID ?? "",
|
|
31
|
+
sourceSaeId: data.source_SAE_ID ?? this.sourceSaeId,
|
|
32
|
+
destinationSaeId: data.destination_SAE_ID ?? this.destinationSaeId,
|
|
33
|
+
keySize: data.key_size ?? 256,
|
|
34
|
+
storedKeyCount: data.stored_key_count ?? 0,
|
|
35
|
+
maxKeyCount: data.max_key_count ?? 0,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async getEncKeys(number = 1, size = 256) {
|
|
39
|
+
const url = `${this.baseUrl}/api/v1/keys/${this.destinationSaeId}/enc_keys`;
|
|
40
|
+
const res = await fetch(url, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
43
|
+
body: JSON.stringify({ number, size }),
|
|
44
|
+
});
|
|
45
|
+
if (!res.ok) {
|
|
46
|
+
throw new Error(`ETSI enc_keys failed: HTTP ${res.status}`);
|
|
47
|
+
}
|
|
48
|
+
const data = await res.json();
|
|
49
|
+
return (data.keys ?? []).map((k) => {
|
|
50
|
+
const buffer = Buffer.from(k.key, "base64");
|
|
51
|
+
return {
|
|
52
|
+
keyId: k.key_ID,
|
|
53
|
+
keyBytes: new Uint8Array(buffer),
|
|
54
|
+
sizeBits: size,
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async getDecKeys(keyIds) {
|
|
59
|
+
const url = `${this.baseUrl}/api/v1/keys/${this.destinationSaeId}/dec_keys`;
|
|
60
|
+
const res = await fetch(url, {
|
|
61
|
+
method: "POST",
|
|
62
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
63
|
+
body: JSON.stringify({ key_IDs: keyIds.map((id) => ({ key_ID: id })) }),
|
|
64
|
+
});
|
|
65
|
+
if (!res.ok) {
|
|
66
|
+
throw new Error(`ETSI dec_keys failed: HTTP ${res.status}`);
|
|
67
|
+
}
|
|
68
|
+
const data = await res.json();
|
|
69
|
+
return (data.keys ?? []).map((k) => {
|
|
70
|
+
const buffer = Buffer.from(k.key, "base64");
|
|
71
|
+
return {
|
|
72
|
+
keyId: k.key_ID,
|
|
73
|
+
keyBytes: new Uint8Array(buffer),
|
|
74
|
+
sizeBits: buffer.length * 8,
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.ETSI014Client = ETSI014Client;
|
|
80
|
+
class QIDSClient {
|
|
81
|
+
nodeId;
|
|
82
|
+
etsiKmsUrl;
|
|
83
|
+
timeoutMs;
|
|
84
|
+
constructor(config) {
|
|
85
|
+
this.nodeId = config.nodeId;
|
|
86
|
+
this.etsiKmsUrl = config.etsiKmsUrl;
|
|
87
|
+
this.timeoutMs = config.timeoutMs ?? 10000;
|
|
88
|
+
}
|
|
89
|
+
getEtsiClient(peerSaeId) {
|
|
90
|
+
if (!this.etsiKmsUrl) {
|
|
91
|
+
throw new Error("etsiKmsUrl is required to connect to ETSI GS QKD 014 Key Management Entity");
|
|
92
|
+
}
|
|
93
|
+
return new ETSI014Client(this.etsiKmsUrl, this.nodeId, peerSaeId);
|
|
94
|
+
}
|
|
95
|
+
async sign(documentId, payload, recipientIds) {
|
|
96
|
+
const payloadBytes = typeof payload === "string" ? Buffer.from(payload, "utf-8") : Buffer.from(payload);
|
|
97
|
+
const docHash = (0, node_crypto_1.createHash)("sha3-256").update(payloadBytes).digest("hex");
|
|
98
|
+
const timestamp = Date.now();
|
|
99
|
+
const tags = [];
|
|
100
|
+
for (const rid of recipientIds) {
|
|
101
|
+
let keyId;
|
|
102
|
+
if (this.etsiKmsUrl) {
|
|
103
|
+
const etsi = this.getEtsiClient(rid);
|
|
104
|
+
const keys = await etsi.getEncKeys(1, 256);
|
|
105
|
+
keyId = keys[0].keyId;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
keyId = `local-ephemeral-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
109
|
+
}
|
|
110
|
+
const tagHasher = (0, node_crypto_1.createHash)("sha3-256");
|
|
111
|
+
tagHasher.update(payloadBytes);
|
|
112
|
+
tagHasher.update(Buffer.from(keyId, "utf-8"));
|
|
113
|
+
const tagHex = tagHasher.digest("hex");
|
|
114
|
+
tags.push({
|
|
115
|
+
recipientSaeId: rid,
|
|
116
|
+
hashTagHex: tagHex,
|
|
117
|
+
tagLengthBits: 256,
|
|
118
|
+
keyId,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
documentId,
|
|
123
|
+
documentHash: docHash,
|
|
124
|
+
signatureTags: tags,
|
|
125
|
+
signedAtUtcMs: timestamp,
|
|
126
|
+
algorithm: "QIDS-OTUH-256",
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
async verify(documentId, payload, senderId, signatureTag) {
|
|
130
|
+
const payloadBytes = typeof payload === "string" ? Buffer.from(payload, "utf-8") : Buffer.from(payload);
|
|
131
|
+
let keyId = signatureTag.keyId;
|
|
132
|
+
if (this.etsiKmsUrl) {
|
|
133
|
+
const etsi = this.getEtsiClient(senderId);
|
|
134
|
+
const decKeys = await etsi.getDecKeys([keyId]);
|
|
135
|
+
keyId = decKeys[0].keyId;
|
|
136
|
+
}
|
|
137
|
+
const tagHasher = (0, node_crypto_1.createHash)("sha3-256");
|
|
138
|
+
tagHasher.update(payloadBytes);
|
|
139
|
+
tagHasher.update(Buffer.from(keyId, "utf-8"));
|
|
140
|
+
const computedTag = tagHasher.digest("hex");
|
|
141
|
+
const isValid = (computedTag === signatureTag.hashTagHex);
|
|
142
|
+
return {
|
|
143
|
+
documentId,
|
|
144
|
+
isValid,
|
|
145
|
+
observedErrorRate: isValid ? 0.0 : 1.0,
|
|
146
|
+
thresholdErrorRate: 0.1111,
|
|
147
|
+
bitMismatches: isValid ? 0 : 256,
|
|
148
|
+
reason: isValid ? "ACCEPTED" : "TAG_MISMATCH_POTENTIAL_FORGERY",
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.QIDSClient = QIDSClient;
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "qids-sdk",
|
|
3
|
+
"version": "1.3.2",
|
|
4
|
+
"description": "Official TypeScript and Node.js SDK for Quantum Digital Signatures (QDS) & Post-Quantum Security",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md",
|
|
10
|
+
"LICENSE"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"quantum",
|
|
18
|
+
"cryptography",
|
|
19
|
+
"quantum-digital-signatures",
|
|
20
|
+
"post-quantum",
|
|
21
|
+
"qkd",
|
|
22
|
+
"etsi-014",
|
|
23
|
+
"qids"
|
|
24
|
+
],
|
|
25
|
+
"author": "QIDS Engineering Team",
|
|
26
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^22.0.0",
|
|
29
|
+
"typescript": "^5.3.3"
|
|
30
|
+
}
|
|
31
|
+
}
|