@keetanetwork/anchor 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.
- package/.done +0 -0
- package/LICENSE +35 -0
- package/client/index.d.ts +10 -0
- package/client/index.d.ts.map +1 -0
- package/client/index.js +11 -0
- package/client/index.js.map +1 -0
- package/config.d.ts +10 -0
- package/config.d.ts.map +1 -0
- package/config.js +36 -0
- package/config.js.map +1 -0
- package/lib/certificates.d.ts +106 -0
- package/lib/certificates.d.ts.map +1 -0
- package/lib/certificates.js +463 -0
- package/lib/certificates.js.map +1 -0
- package/lib/encrypted-container.d.ts +106 -0
- package/lib/encrypted-container.d.ts.map +1 -0
- package/lib/encrypted-container.js +594 -0
- package/lib/encrypted-container.js.map +1 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +5 -0
- package/lib/index.js.map +1 -0
- package/lib/log/common.d.ts +35 -0
- package/lib/log/common.d.ts.map +1 -0
- package/lib/log/common.js +19 -0
- package/lib/log/common.js.map +1 -0
- package/lib/log/index.d.ts +59 -0
- package/lib/log/index.d.ts.map +1 -0
- package/lib/log/index.js +207 -0
- package/lib/log/index.js.map +1 -0
- package/lib/log/target_console.d.ts +13 -0
- package/lib/log/target_console.d.ts.map +1 -0
- package/lib/log/target_console.js +44 -0
- package/lib/log/target_console.js.map +1 -0
- package/lib/resolver.d.ts +308 -0
- package/lib/resolver.d.ts.map +1 -0
- package/lib/resolver.js +1429 -0
- package/lib/resolver.js.map +1 -0
- package/lib/utils/array.d.ts +10 -0
- package/lib/utils/array.d.ts.map +1 -0
- package/lib/utils/array.js +12 -0
- package/lib/utils/array.js.map +1 -0
- package/lib/utils/asn1.d.ts +13 -0
- package/lib/utils/asn1.d.ts.map +1 -0
- package/lib/utils/asn1.js +8 -0
- package/lib/utils/asn1.js.map +1 -0
- package/lib/utils/buffer.d.ts +4 -0
- package/lib/utils/buffer.d.ts.map +1 -0
- package/lib/utils/buffer.js +3 -0
- package/lib/utils/buffer.js.map +1 -0
- package/lib/utils/crypto.d.ts +4 -0
- package/lib/utils/crypto.d.ts.map +1 -0
- package/lib/utils/crypto.js +4 -0
- package/lib/utils/crypto.js.map +1 -0
- package/lib/utils/index.d.ts +5 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/index.js +5 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/json.d.ts +8 -0
- package/lib/utils/json.d.ts.map +1 -0
- package/lib/utils/json.js +164 -0
- package/lib/utils/json.js.map +1 -0
- package/lib/utils/never.d.ts +8 -0
- package/lib/utils/never.d.ts.map +1 -0
- package/lib/utils/never.js +14 -0
- package/lib/utils/never.js.map +1 -0
- package/npm-shrinkwrap.json +16517 -0
- package/package.json +42 -0
- package/services/kyc/client.d.ts +139 -0
- package/services/kyc/client.d.ts.map +1 -0
- package/services/kyc/client.js +390 -0
- package/services/kyc/client.js.map +1 -0
- package/services/kyc/common.d.ts +65 -0
- package/services/kyc/common.d.ts.map +1 -0
- package/services/kyc/common.js +2 -0
- package/services/kyc/common.js.map +1 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import * as KeetaNetClient from '@keetanetwork/keetanet-client';
|
|
2
|
+
import * as ASN1 from './utils/asn1.js';
|
|
3
|
+
import { Buffer } from './utils/buffer.js';
|
|
4
|
+
import crypto from './utils/crypto.js';
|
|
5
|
+
import { assertNever } from './utils/never.js';
|
|
6
|
+
/* -----MOVE TO NODE AND ASN1NAPIRS----- */
|
|
7
|
+
function getOID(name, oidDB) {
|
|
8
|
+
if (name in oidDB) {
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
10
|
+
const oid = oidDB[name];
|
|
11
|
+
if (oid === undefined) {
|
|
12
|
+
throw (new Error('internal error: OID was undefined'));
|
|
13
|
+
}
|
|
14
|
+
return (oid);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
throw (new Error('Unknown algorithm'));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function lookupByOID(oid, oidDB) {
|
|
21
|
+
for (const [key, value] of Object.entries(oidDB)) {
|
|
22
|
+
if (key === oid) {
|
|
23
|
+
return (key);
|
|
24
|
+
}
|
|
25
|
+
if (value === oid) {
|
|
26
|
+
return (key);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
throw (new Error(`Unknown OID: ${oid}`));
|
|
30
|
+
}
|
|
31
|
+
/* -----END MOVE TO NODE AND ASN1NAPIRS----- */
|
|
32
|
+
function toJSON(data) {
|
|
33
|
+
const retval = JSON.parse(JSON.stringify(data, function (key, convertedValue) {
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
35
|
+
const value = this[key];
|
|
36
|
+
if (typeof value === 'object' && value !== null) {
|
|
37
|
+
if ('publicKeyString' in value && typeof value.publicKeyString === 'object' && value.publicKeyString !== null) {
|
|
38
|
+
if ('get' in value.publicKeyString && typeof value.publicKeyString.get === 'function') {
|
|
39
|
+
/*
|
|
40
|
+
* If the value has a publicKeyString property that is an
|
|
41
|
+
* object with a get method, we assume it is a KeetaNetAccount
|
|
42
|
+
* or similar object and we return the public key string
|
|
43
|
+
*/
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
45
|
+
const publicKeyString = value.publicKeyString.get();
|
|
46
|
+
if (typeof publicKeyString === 'string') {
|
|
47
|
+
return (publicKeyString);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (Buffer.isBuffer(value)) {
|
|
53
|
+
return (value.toString('base64'));
|
|
54
|
+
}
|
|
55
|
+
if (typeof value === 'bigint') {
|
|
56
|
+
return (value.toString());
|
|
57
|
+
}
|
|
58
|
+
return (convertedValue);
|
|
59
|
+
}));
|
|
60
|
+
return (retval);
|
|
61
|
+
}
|
|
62
|
+
/*
|
|
63
|
+
* Because our public interfaces are ArrayBuffers we often need to convert
|
|
64
|
+
* Buffers to ArrayBuffers -- an alias to the Node function to do that
|
|
65
|
+
*/
|
|
66
|
+
const bufferToArrayBuffer = KeetaNetClient.lib.Utils.Helper.bufferToArrayBuffer.bind(KeetaNetClient.lib.Utils.Helper);
|
|
67
|
+
/**
|
|
68
|
+
* Sensitive Attribute Schema
|
|
69
|
+
*
|
|
70
|
+
* ASN.1 Schema:
|
|
71
|
+
* SensitiveAttributes DEFINITIONS ::= BEGIN
|
|
72
|
+
* SensitiveAttribute ::= SEQUENCE {
|
|
73
|
+
* version INTEGER { v1(0) },
|
|
74
|
+
* cipher SEQUENCE {
|
|
75
|
+
* algorithm OBJECT IDENTIFIER,
|
|
76
|
+
* ivOrNonce OCTET STRING,
|
|
77
|
+
* key OCTET STRING
|
|
78
|
+
* },
|
|
79
|
+
* hashedValue SEQUENCE {
|
|
80
|
+
* encryptedSalt OCTET STRING,
|
|
81
|
+
* algorithm OBJECT IDENTIFIER,
|
|
82
|
+
* value OCTET STRING
|
|
83
|
+
* },
|
|
84
|
+
* encryptedValue OCTET STRING
|
|
85
|
+
* }
|
|
86
|
+
* END
|
|
87
|
+
*
|
|
88
|
+
* https://keeta.notion.site/Keeta-KYC-Certificate-Extensions-13e5da848e588042bdcef81fc40458b7
|
|
89
|
+
*
|
|
90
|
+
* @internal
|
|
91
|
+
*/
|
|
92
|
+
const SensitiveAttributeSchemaInternal = [
|
|
93
|
+
0n,
|
|
94
|
+
[
|
|
95
|
+
ASN1.ValidateASN1.IsOID,
|
|
96
|
+
ASN1.ValidateASN1.IsOctetString,
|
|
97
|
+
ASN1.ValidateASN1.IsOctetString
|
|
98
|
+
],
|
|
99
|
+
[
|
|
100
|
+
ASN1.ValidateASN1.IsOctetString,
|
|
101
|
+
ASN1.ValidateASN1.IsOID,
|
|
102
|
+
ASN1.ValidateASN1.IsOctetString
|
|
103
|
+
],
|
|
104
|
+
ASN1.ValidateASN1.IsOctetString
|
|
105
|
+
];
|
|
106
|
+
/*
|
|
107
|
+
* Database of permitted algorithms and their OIDs
|
|
108
|
+
*/
|
|
109
|
+
const sensitiveAttributeOIDDB = {
|
|
110
|
+
'aes-256-gcm': '2.16.840.1.101.3.4.1.46',
|
|
111
|
+
'aes-256-cbc': '2.16.840.1.101.3.4.1.42',
|
|
112
|
+
'sha2-256': '2.16.840.1.101.3.4.2.1',
|
|
113
|
+
'sha3-256': '2.16.840.1.101.3.4.2.8'
|
|
114
|
+
};
|
|
115
|
+
class SensitiveAttributeBuilder {
|
|
116
|
+
#account;
|
|
117
|
+
#value;
|
|
118
|
+
constructor(account, value) {
|
|
119
|
+
this.#account = account;
|
|
120
|
+
if (value) {
|
|
121
|
+
this.set(value);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
set(value) {
|
|
125
|
+
if (Buffer.isBuffer(value)) {
|
|
126
|
+
this.#value = value;
|
|
127
|
+
}
|
|
128
|
+
else if (typeof value === 'string') {
|
|
129
|
+
this.#value = Buffer.from(value, 'utf-8');
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
this.#value = Buffer.from(value);
|
|
133
|
+
}
|
|
134
|
+
return (this);
|
|
135
|
+
}
|
|
136
|
+
async build() {
|
|
137
|
+
if (this.#value === undefined) {
|
|
138
|
+
throw (new Error('Value not set'));
|
|
139
|
+
}
|
|
140
|
+
const salt = crypto.randomBytes(32);
|
|
141
|
+
const hashingAlgorithm = KeetaNetClient.lib.Utils.Hash.HashFunctionName;
|
|
142
|
+
const publicKey = Buffer.from(this.#account.publicKey.get());
|
|
143
|
+
const cipher = 'aes-256-gcm';
|
|
144
|
+
const key = crypto.randomBytes(32);
|
|
145
|
+
const nonce = crypto.randomBytes(12);
|
|
146
|
+
const encryptedKey = await this.#account.encrypt(key);
|
|
147
|
+
function encrypt(value) {
|
|
148
|
+
const cipherObject = crypto.createCipheriv(cipher, key, nonce);
|
|
149
|
+
let retval = cipherObject.update(value);
|
|
150
|
+
retval = Buffer.concat([retval, cipherObject.final()]);
|
|
151
|
+
return (retval);
|
|
152
|
+
}
|
|
153
|
+
const encryptedValue = encrypt(this.#value);
|
|
154
|
+
const encryptedSalt = encrypt(salt);
|
|
155
|
+
const saltedValue = Buffer.concat([salt, publicKey, encryptedValue, this.#value]);
|
|
156
|
+
const hashedAndSaltedValue = KeetaNetClient.lib.Utils.Hash.Hash(saltedValue);
|
|
157
|
+
const attributeStructure = [
|
|
158
|
+
/* Version */
|
|
159
|
+
0n,
|
|
160
|
+
/* Cipher Details */
|
|
161
|
+
[
|
|
162
|
+
/* Algorithm */
|
|
163
|
+
{ type: 'oid', oid: getOID(cipher, sensitiveAttributeOIDDB) },
|
|
164
|
+
/* IV or Nonce */
|
|
165
|
+
nonce,
|
|
166
|
+
/* Symmetric key, encrypted with the public key of the account */
|
|
167
|
+
Buffer.from(encryptedKey)
|
|
168
|
+
],
|
|
169
|
+
/* Hashed Value */
|
|
170
|
+
[
|
|
171
|
+
/* Encrypted Salt */
|
|
172
|
+
Buffer.from(encryptedSalt),
|
|
173
|
+
/* Hashing Algorithm */
|
|
174
|
+
{ type: 'oid', oid: getOID(hashingAlgorithm, sensitiveAttributeOIDDB) },
|
|
175
|
+
/* Hash of <Encrypted Salt> || <Public Key> || <Value> */
|
|
176
|
+
Buffer.from(hashedAndSaltedValue)
|
|
177
|
+
],
|
|
178
|
+
/* Encrypted Value, encrypted with the Cipher above */
|
|
179
|
+
encryptedValue
|
|
180
|
+
];
|
|
181
|
+
const encodedAttributeObject = ASN1.JStoASN1(attributeStructure);
|
|
182
|
+
const retval = encodedAttributeObject.toBER();
|
|
183
|
+
return (retval);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
class SensitiveAttribute {
|
|
187
|
+
#account;
|
|
188
|
+
#info;
|
|
189
|
+
constructor(account, data) {
|
|
190
|
+
this.#account = account;
|
|
191
|
+
this.#info = this.decode(data);
|
|
192
|
+
}
|
|
193
|
+
decode(data) {
|
|
194
|
+
if (Buffer.isBuffer(data)) {
|
|
195
|
+
data = bufferToArrayBuffer(data);
|
|
196
|
+
}
|
|
197
|
+
const dataObject = new ASN1.BufferStorageASN1(data, SensitiveAttributeSchemaInternal);
|
|
198
|
+
const decodedAttribute = dataObject.getASN1();
|
|
199
|
+
const decodedVersion = decodedAttribute[0] + 1n;
|
|
200
|
+
if (decodedVersion !== 1n) {
|
|
201
|
+
throw (new Error(`Unsupported Sensitive Attribute version (${decodedVersion})`));
|
|
202
|
+
}
|
|
203
|
+
return ({
|
|
204
|
+
version: decodedVersion,
|
|
205
|
+
publicKey: this.#account.publicKeyString.get(),
|
|
206
|
+
cipher: {
|
|
207
|
+
algorithm: lookupByOID(decodedAttribute[1][0].oid, sensitiveAttributeOIDDB),
|
|
208
|
+
iv: decodedAttribute[1][1],
|
|
209
|
+
key: decodedAttribute[1][2]
|
|
210
|
+
},
|
|
211
|
+
hashedValue: {
|
|
212
|
+
encryptedSalt: decodedAttribute[2][0],
|
|
213
|
+
algorithm: lookupByOID(decodedAttribute[2][1].oid, sensitiveAttributeOIDDB),
|
|
214
|
+
value: decodedAttribute[2][2]
|
|
215
|
+
},
|
|
216
|
+
encryptedValue: decodedAttribute[3]
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async #decryptValue(value) {
|
|
220
|
+
const decryptedKey = await this.#account.decrypt(this.#info.cipher.key);
|
|
221
|
+
const algorithm = this.#info.cipher.algorithm;
|
|
222
|
+
const iv = this.#info.cipher.iv;
|
|
223
|
+
const cipher = crypto.createDecipheriv(algorithm, Buffer.from(decryptedKey), iv);
|
|
224
|
+
const decryptedValue = cipher.update(value);
|
|
225
|
+
return (decryptedValue);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get the value of the sensitive attribute
|
|
229
|
+
*
|
|
230
|
+
* This will decrypt the value using the account's private key
|
|
231
|
+
* and return the value as an ArrayBuffer
|
|
232
|
+
*
|
|
233
|
+
* Since sensitive attributes are binary blobs, this returns an
|
|
234
|
+
* ArrayBuffer
|
|
235
|
+
*/
|
|
236
|
+
async get() {
|
|
237
|
+
const decryptedValue = await this.#decryptValue(this.#info.encryptedValue);
|
|
238
|
+
return (bufferToArrayBuffer(decryptedValue));
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get the value of the sensitive attribute as a string after being
|
|
242
|
+
* interpreted as UTF-8 ( @see SensitiveAttribute.get for more information)
|
|
243
|
+
*/
|
|
244
|
+
async getString() {
|
|
245
|
+
const value = await this.get();
|
|
246
|
+
return (Buffer.from(value).toString('utf-8'));
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Generate a proof that a sensitive attribute is a given value,
|
|
250
|
+
* which can be validated by a third party using the certificate
|
|
251
|
+
* and the `validateProof` method
|
|
252
|
+
*/
|
|
253
|
+
async proove() {
|
|
254
|
+
const value = await this.get();
|
|
255
|
+
const salt = await this.#decryptValue(this.#info.hashedValue.encryptedSalt);
|
|
256
|
+
return ({
|
|
257
|
+
value: Buffer.from(value).toString('base64'),
|
|
258
|
+
hash: {
|
|
259
|
+
salt: salt.toString('base64')
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Validate the proof that a sensitive attribute is a given value
|
|
265
|
+
*/
|
|
266
|
+
async validateProof(proof) {
|
|
267
|
+
const plaintextValue = Buffer.from(proof.value, 'base64');
|
|
268
|
+
const proofSaltBuffer = Buffer.from(proof.hash.salt, 'base64');
|
|
269
|
+
const publicKeyBuffer = Buffer.from(this.#account.publicKey.get());
|
|
270
|
+
const encryptedValue = this.#info.encryptedValue;
|
|
271
|
+
const hashedAndSaltedValue = KeetaNetClient.lib.Utils.Hash.Hash(Buffer.concat([proofSaltBuffer, publicKeyBuffer, encryptedValue, plaintextValue]));
|
|
272
|
+
const hashedAndSaltedValueBuffer = Buffer.from(hashedAndSaltedValue);
|
|
273
|
+
return (this.#info.hashedValue.value.equals(hashedAndSaltedValueBuffer));
|
|
274
|
+
}
|
|
275
|
+
toJSON() {
|
|
276
|
+
return (toJSON(this.#info));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Database of attributes
|
|
281
|
+
*/
|
|
282
|
+
const CertificateAttributeOIDDB = {
|
|
283
|
+
'fullName': '1.3.6.1.4.1.62675.1.0',
|
|
284
|
+
'dateOfBirth': '1.3.6.1.4.1.62675.1.1',
|
|
285
|
+
'address': '1.3.6.1.4.1.62675.1.2',
|
|
286
|
+
'email': '1.3.6.1.4.1.62675.1.3',
|
|
287
|
+
'phoneNumber': '1.3.6.1.4.1.62675.1.4'
|
|
288
|
+
};
|
|
289
|
+
/**
|
|
290
|
+
* ASN.1 Schema for Certificate KYC Attributes Extension
|
|
291
|
+
*
|
|
292
|
+
* KYCAttributes DEFINITIONS ::= BEGIN
|
|
293
|
+
* KYCAttributes ::= SEQUENCE OF Attribute
|
|
294
|
+
* Attribute ::= SEQUENCE {
|
|
295
|
+
* -- Name of the attribute
|
|
296
|
+
* name OBJECT IDENTIFIER,
|
|
297
|
+
* -- Value of this attribute
|
|
298
|
+
* value CHOICE {
|
|
299
|
+
* -- A plain value, not sensitive
|
|
300
|
+
* plainValue [0] IMPLICIT OCTET STRING,
|
|
301
|
+
* -- A sensitive value, encoded as a SensitiveAttribute in DER encoding
|
|
302
|
+
* sensitiveValue [1] IMPLICIT OCTET STRING
|
|
303
|
+
* }
|
|
304
|
+
* }
|
|
305
|
+
* END
|
|
306
|
+
*
|
|
307
|
+
* https://keeta.notion.site/Keeta-KYC-Certificate-Extensions-13e5da848e588042bdcef81fc40458b7
|
|
308
|
+
*
|
|
309
|
+
*/
|
|
310
|
+
const CertificateKYCAttributeSchemaValidation = {
|
|
311
|
+
sequenceOf: [ASN1.ValidateASN1.IsOID, {
|
|
312
|
+
choice: [
|
|
313
|
+
{ type: 'context', value: 0, kind: 'implicit', contains: ASN1.ValidateASN1.IsOctetString },
|
|
314
|
+
{ type: 'context', value: 1, kind: 'implicit', contains: ASN1.ValidateASN1.IsOctetString }
|
|
315
|
+
]
|
|
316
|
+
}]
|
|
317
|
+
};
|
|
318
|
+
export class CertificateBuilder extends KeetaNetClient.lib.Utils.Certificate.CertificateBuilder {
|
|
319
|
+
#attributes = {};
|
|
320
|
+
/**
|
|
321
|
+
* Map the parameters from the public interface to the internal
|
|
322
|
+
* (Certificate library) interface
|
|
323
|
+
*/
|
|
324
|
+
static mapParams(params) {
|
|
325
|
+
const paramsCopy = { ...params };
|
|
326
|
+
let subjectPublicKey;
|
|
327
|
+
if (paramsCopy.subject) {
|
|
328
|
+
subjectPublicKey = paramsCopy.subject;
|
|
329
|
+
delete (paramsCopy.subject);
|
|
330
|
+
}
|
|
331
|
+
const retval = paramsCopy;
|
|
332
|
+
if (subjectPublicKey) {
|
|
333
|
+
retval.subjectPublicKey = subjectPublicKey;
|
|
334
|
+
}
|
|
335
|
+
return (retval);
|
|
336
|
+
}
|
|
337
|
+
constructor(params) {
|
|
338
|
+
super(CertificateBuilder.mapParams(params));
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Set a KYC Attribute to a given value
|
|
342
|
+
*/
|
|
343
|
+
setAttribute(name, sensitive, value) {
|
|
344
|
+
this.#attributes[name] = { sensitive, value };
|
|
345
|
+
}
|
|
346
|
+
async addExtensions(...args) {
|
|
347
|
+
const retval = await super.addExtensions(...args);
|
|
348
|
+
const subject = args[0].subjectPublicKey;
|
|
349
|
+
/* Encode the attributes */
|
|
350
|
+
const certAttributes = [];
|
|
351
|
+
for (const [name, attribute] of Object.entries(this.#attributes)) {
|
|
352
|
+
if (!(name in CertificateAttributeOIDDB)) {
|
|
353
|
+
throw (new Error(`Unknown attribute: ${name}`));
|
|
354
|
+
}
|
|
355
|
+
/*
|
|
356
|
+
* Since we are iteratively building the certificate, we
|
|
357
|
+
* can assume that the attribute is always present in
|
|
358
|
+
* the object
|
|
359
|
+
*/
|
|
360
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
361
|
+
const nameOID = CertificateAttributeOIDDB[name];
|
|
362
|
+
let value;
|
|
363
|
+
if (attribute.sensitive) {
|
|
364
|
+
const sensitiveAttribute = new SensitiveAttributeBuilder(subject, attribute.value);
|
|
365
|
+
value = Buffer.from(await sensitiveAttribute.build());
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
if (typeof attribute.value === 'string') {
|
|
369
|
+
value = Buffer.from(attribute.value, 'utf-8');
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
value = Buffer.from(attribute.value);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
certAttributes.push([{
|
|
376
|
+
type: 'oid',
|
|
377
|
+
oid: nameOID
|
|
378
|
+
}, {
|
|
379
|
+
type: 'context',
|
|
380
|
+
kind: 'implicit',
|
|
381
|
+
value: attribute.sensitive ? 1 : 0,
|
|
382
|
+
contains: value
|
|
383
|
+
}]);
|
|
384
|
+
}
|
|
385
|
+
if (certAttributes.length > 0) {
|
|
386
|
+
retval.push(KeetaNetClient.lib.Utils.Certificate.CertificateBuilder.extension('1.3.6.1.4.1.62675.0.0', certAttributes));
|
|
387
|
+
}
|
|
388
|
+
return (retval);
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Create a Certificate object from the builder
|
|
392
|
+
*
|
|
393
|
+
* The parameters passed in are merged with the parameters passed in
|
|
394
|
+
* when constructing the builder
|
|
395
|
+
*/
|
|
396
|
+
async build(params) {
|
|
397
|
+
const paramsCopy = CertificateBuilder.mapParams(params);
|
|
398
|
+
const certificate = await super.buildDER(paramsCopy);
|
|
399
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
400
|
+
const certificateObject = new Certificate(certificate, {
|
|
401
|
+
/**
|
|
402
|
+
* Specify the moment as `null` to avoid validation
|
|
403
|
+
* of the certificate's validity period. We don't
|
|
404
|
+
* care if the certificate is expired or not for
|
|
405
|
+
* the purposes of this builder.
|
|
406
|
+
*/
|
|
407
|
+
moment: null
|
|
408
|
+
});
|
|
409
|
+
return (certificateObject);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
export class Certificate extends KeetaNetClient.lib.Utils.Certificate.Certificate {
|
|
413
|
+
subjectKey;
|
|
414
|
+
static Builder = CertificateBuilder;
|
|
415
|
+
/**
|
|
416
|
+
* User KYC Attributes
|
|
417
|
+
*/
|
|
418
|
+
attributes = {};
|
|
419
|
+
constructor(input, options) {
|
|
420
|
+
super(input, options);
|
|
421
|
+
this.subjectKey = options?.subjectKey ?? this.subjectPublicKey;
|
|
422
|
+
super.finalizeConstruction();
|
|
423
|
+
}
|
|
424
|
+
finalizeConstruction() {
|
|
425
|
+
/* Do nothing, we call the super method in the constructor */
|
|
426
|
+
}
|
|
427
|
+
processExtension(id, value) {
|
|
428
|
+
if (super.processExtension(id, value)) {
|
|
429
|
+
return (true);
|
|
430
|
+
}
|
|
431
|
+
if (id === '1.3.6.1.4.1.62675.0.0') {
|
|
432
|
+
const attributesRaw = new ASN1.BufferStorageASN1(value, CertificateKYCAttributeSchemaValidation).getASN1();
|
|
433
|
+
for (const attribute of attributesRaw) {
|
|
434
|
+
const name = lookupByOID(attribute[0].oid, CertificateAttributeOIDDB);
|
|
435
|
+
const valueKind = attribute[1].value;
|
|
436
|
+
const value = bufferToArrayBuffer(attribute[1].contains);
|
|
437
|
+
switch (valueKind) {
|
|
438
|
+
case 0:
|
|
439
|
+
/* Plain Value */
|
|
440
|
+
this.attributes[name] = { sensitive: false, value: value };
|
|
441
|
+
break;
|
|
442
|
+
case 1:
|
|
443
|
+
/* Sensitive Value */
|
|
444
|
+
this.attributes[name] = {
|
|
445
|
+
sensitive: true,
|
|
446
|
+
value: new SensitiveAttribute(this.subjectKey, value)
|
|
447
|
+
};
|
|
448
|
+
break;
|
|
449
|
+
default:
|
|
450
|
+
assertNever(valueKind);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return (true);
|
|
454
|
+
}
|
|
455
|
+
return (false);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
/** @internal */
|
|
459
|
+
export const _Testing = {
|
|
460
|
+
SensitiveAttributeBuilder,
|
|
461
|
+
SensitiveAttribute
|
|
462
|
+
};
|
|
463
|
+
//# sourceMappingURL=certificates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certificates.js","sourceRoot":"","sources":["../../src/lib/certificates.ts"],"names":[],"mappings":"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","sourcesContent":["import * as KeetaNetClient from '@keetanetwork/keetanet-client';\nimport * as ASN1 from './utils/asn1.js';\nimport { Buffer } from './utils/buffer.js';\nimport crypto from './utils/crypto.js';\nimport { assertNever } from './utils/never.js';\n\n/* ENUM */\ntype AccountKeyAlgorithm = InstanceType<typeof KeetaNetClient.lib.Account>['keyType'];\n\n/**\n * An alias for the KeetaNetAccount type\n */\ntype KeetaNetAccount = ReturnType<typeof KeetaNetClient.lib.Account.fromSeed<AccountKeyAlgorithm>>;\n\n/* -----MOVE TO NODE AND ASN1NAPIRS----- */\nfunction getOID(name: string, oidDB: { [name: string]: string }) {\n\tif (name in oidDB) {\n\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\tconst oid = oidDB[name as keyof typeof oidDB];\n\t\tif (oid === undefined) {\n\t\t\tthrow(new Error('internal error: OID was undefined'));\n\t\t}\n\n\t\treturn(oid);\n\t} else {\n\t\tthrow(new Error('Unknown algorithm'));\n\t}\n}\n\nfunction lookupByOID(oid: string, oidDB: { [name: string]: string }) {\n\tfor (const [key, value] of Object.entries(oidDB)) {\n\t\tif (key === oid) {\n\t\t\treturn(key);\n\t\t}\n\n\t\tif (value === oid) {\n\t\t\treturn(key);\n\t\t}\n\t}\n\n\tthrow(new Error(`Unknown OID: ${oid}`));\n}\n/* -----END MOVE TO NODE AND ASN1NAPIRS----- */\n\nfunction toJSON(data: unknown): unknown {\n\tconst retval: unknown = JSON.parse(JSON.stringify(data, function(key, convertedValue: unknown) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\tconst value: unknown = this[key];\n\n\t\tif (typeof value === 'object' && value !== null) {\n\t\t\tif ('publicKeyString' in value && typeof value.publicKeyString === 'object' && value.publicKeyString !== null) {\n\t\t\t\tif ('get' in value.publicKeyString && typeof value.publicKeyString.get === 'function') {\n\t\t\t\t\t/*\n\t\t\t\t\t * If the value has a publicKeyString property that is an\n\t\t\t\t\t * object with a get method, we assume it is a KeetaNetAccount\n\t\t\t\t\t * or similar object and we return the public key string\n\t\t\t\t\t */\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\t\t\t\tconst publicKeyString: unknown = value.publicKeyString.get();\n\t\t\t\t\tif (typeof publicKeyString === 'string') {\n\t\t\t\t\t\treturn(publicKeyString);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Buffer.isBuffer(value)) {\n\t\t\treturn(value.toString('base64'));\n\t\t}\n\t\tif (typeof value === 'bigint') {\n\t\t\treturn(value.toString());\n\t\t}\n\n\t\treturn(convertedValue);\n\t}));\n\n\treturn(retval);\n}\n\n/*\n * Because our public interfaces are ArrayBuffers we often need to convert\n * Buffers to ArrayBuffers -- an alias to the Node function to do that\n */\nconst bufferToArrayBuffer = KeetaNetClient.lib.Utils.Helper.bufferToArrayBuffer.bind(KeetaNetClient.lib.Utils.Helper);\n\n/**\n * Sensitive Attribute Schema\n *\n * ASN.1 Schema:\n * SensitiveAttributes DEFINITIONS ::= BEGIN\n * SensitiveAttribute ::= SEQUENCE {\n * version INTEGER { v1(0) },\n * cipher SEQUENCE {\n * algorithm OBJECT IDENTIFIER,\n * ivOrNonce OCTET STRING,\n * key OCTET STRING\n * },\n * hashedValue SEQUENCE {\n * encryptedSalt OCTET STRING,\n * algorithm OBJECT IDENTIFIER,\n * value OCTET STRING\n * },\n * encryptedValue OCTET STRING\n * }\n * END\n *\n * https://keeta.notion.site/Keeta-KYC-Certificate-Extensions-13e5da848e588042bdcef81fc40458b7\n *\n * @internal\n */\nconst SensitiveAttributeSchemaInternal: [\n\tversion: 0n,\n\tcipher: [\n\t\talgorithm: typeof ASN1.ValidateASN1.IsOID,\n\t\tiv: typeof ASN1.ValidateASN1.IsOctetString,\n\t\tkey: typeof ASN1.ValidateASN1.IsOctetString\n\t],\n\thashedValue: [\n\t\tencryptedSalt: typeof ASN1.ValidateASN1.IsOctetString,\n\t\talgorithm: typeof ASN1.ValidateASN1.IsOID,\n\t\tvalue: typeof ASN1.ValidateASN1.IsOctetString\n\t],\n\tencryptedValue: typeof ASN1.ValidateASN1.IsOctetString\n] = [\n\t0n,\n\t[\n\t\tASN1.ValidateASN1.IsOID,\n\t\tASN1.ValidateASN1.IsOctetString,\n\t\tASN1.ValidateASN1.IsOctetString\n\t],\n\t[\n\t\tASN1.ValidateASN1.IsOctetString,\n\t\tASN1.ValidateASN1.IsOID,\n\t\tASN1.ValidateASN1.IsOctetString\n\t],\n\tASN1.ValidateASN1.IsOctetString\n];\n\n/**\n * The Sensitive Attribute Schema\n *\n * @internal\n */\ntype SensitiveAttributeSchema = ASN1.SchemaMap<typeof SensitiveAttributeSchemaInternal>;\n\n/*\n * Database of permitted algorithms and their OIDs\n */\nconst sensitiveAttributeOIDDB = {\n\t'aes-256-gcm': '2.16.840.1.101.3.4.1.46',\n\t'aes-256-cbc': '2.16.840.1.101.3.4.1.42',\n\t'sha2-256': '2.16.840.1.101.3.4.2.1',\n\t'sha3-256': '2.16.840.1.101.3.4.2.8'\n};\n\nclass SensitiveAttributeBuilder {\n\treadonly #account: KeetaNetAccount;\n\t#value: Buffer | undefined;\n\n\tconstructor(account: KeetaNetAccount, value?: Buffer | ArrayBuffer | string) {\n\t\tthis.#account = account;\n\n\t\tif (value) {\n\t\t\tthis.set(value);\n\t\t}\n\t}\n\n\tset(value: Buffer | ArrayBuffer | string) {\n\t\tif (Buffer.isBuffer(value)) {\n\t\t\tthis.#value = value;\n\t\t} else if (typeof value === 'string') {\n\t\t\tthis.#value = Buffer.from(value, 'utf-8');\n\t\t} else {\n\t\t\tthis.#value = Buffer.from(value);\n\t\t}\n\n\t\treturn(this);\n\t}\n\n\tasync build() {\n\t\tif (this.#value === undefined) {\n\t\t\tthrow(new Error('Value not set'));\n\t\t}\n\n\t\tconst salt = crypto.randomBytes(32);\n\n\t\tconst hashingAlgorithm = KeetaNetClient.lib.Utils.Hash.HashFunctionName;\n\t\tconst publicKey = Buffer.from(this.#account.publicKey.get());\n\n\t\tconst cipher = 'aes-256-gcm';\n\t\tconst key = crypto.randomBytes(32);\n\t\tconst nonce = crypto.randomBytes(12);\n\t\tconst encryptedKey = await this.#account.encrypt(key);\n\n\t\tfunction encrypt(value: Buffer) {\n\t\t\tconst cipherObject = crypto.createCipheriv(cipher, key, nonce);\n\t\t\tlet retval = cipherObject.update(value);\n\t\t\tretval = Buffer.concat([retval, cipherObject.final()]);\n\t\t\treturn(retval);\n\t\t}\n\n\t\tconst encryptedValue = encrypt(this.#value);\n\t\tconst encryptedSalt = encrypt(salt);\n\n\t\tconst saltedValue = Buffer.concat([salt, publicKey, encryptedValue, this.#value]);\n\t\tconst hashedAndSaltedValue = KeetaNetClient.lib.Utils.Hash.Hash(saltedValue);\n\n\t\tconst attributeStructure: SensitiveAttributeSchema = [\n\t\t\t/* Version */\n\t\t\t0n,\n\t\t\t/* Cipher Details */\n\t\t\t[\n\t\t\t\t/* Algorithm */\n\t\t\t\t{ type: 'oid', oid: getOID(cipher, sensitiveAttributeOIDDB) },\n\t\t\t\t/* IV or Nonce */\n\t\t\t\tnonce,\n\t\t\t\t/* Symmetric key, encrypted with the public key of the account */\n\t\t\t\tBuffer.from(encryptedKey)\n\t\t\t],\n\t\t\t/* Hashed Value */\n\t\t\t[\n\t\t\t\t/* Encrypted Salt */\n\t\t\t\tBuffer.from(encryptedSalt),\n\t\t\t\t/* Hashing Algorithm */\n\t\t\t\t{ type: 'oid', oid: getOID(hashingAlgorithm, sensitiveAttributeOIDDB) },\n\t\t\t\t/* Hash of <Encrypted Salt> || <Public Key> || <Value> */\n\t\t\t\tBuffer.from(hashedAndSaltedValue)\n\t\t\t],\n\t\t\t/* Encrypted Value, encrypted with the Cipher above */\n\t\t\tencryptedValue\n\t\t];\n\t\tconst encodedAttributeObject = ASN1.JStoASN1(attributeStructure);\n\n\t\tconst retval = encodedAttributeObject.toBER();\n\n\t\treturn(retval);\n\t}\n}\n\nclass SensitiveAttribute {\n\treadonly #account: KeetaNetAccount;\n\treadonly #info: ReturnType<SensitiveAttribute['decode']>;\n\n\tconstructor(account: KeetaNetAccount, data: Buffer | ArrayBuffer) {\n\t\tthis.#account = account;\n\t\tthis.#info = this.decode(data);\n\t}\n\n\tprivate decode(data: Buffer | ArrayBuffer) {\n\t\tif (Buffer.isBuffer(data)) {\n\t\t\tdata = bufferToArrayBuffer(data);\n\t\t}\n\n\t\tconst dataObject = new ASN1.BufferStorageASN1(data, SensitiveAttributeSchemaInternal);\n\t\tconst decodedAttribute = dataObject.getASN1();\n\n\t\tconst decodedVersion = decodedAttribute[0] + 1n;\n\t\tif (decodedVersion !== 1n) {\n\t\t\tthrow(new Error(`Unsupported Sensitive Attribute version (${decodedVersion})`));\n\t\t}\n\n\t\treturn({\n\t\t\tversion: decodedVersion,\n\t\t\tpublicKey: this.#account.publicKeyString.get(),\n\t\t\tcipher: {\n\t\t\t\talgorithm: lookupByOID(decodedAttribute[1][0].oid, sensitiveAttributeOIDDB),\n\t\t\t\tiv: decodedAttribute[1][1],\n\t\t\t\tkey: decodedAttribute[1][2]\n\t\t\t},\n\t\t\thashedValue: {\n\t\t\t\tencryptedSalt: decodedAttribute[2][0],\n\t\t\t\talgorithm: lookupByOID(decodedAttribute[2][1].oid, sensitiveAttributeOIDDB),\n\t\t\t\tvalue: decodedAttribute[2][2]\n\t\t\t},\n\t\t\tencryptedValue: decodedAttribute[3]\n\t\t});\n\t}\n\n\tasync #decryptValue(value: Buffer) {\n\t\tconst decryptedKey = await this.#account.decrypt(this.#info.cipher.key);\n\t\tconst algorithm = this.#info.cipher.algorithm;\n\t\tconst iv = this.#info.cipher.iv;\n\n\t\tconst cipher = crypto.createDecipheriv(algorithm, Buffer.from(decryptedKey), iv);\n\t\tconst decryptedValue = cipher.update(value);\n\n\t\treturn(decryptedValue);\n\t}\n\n\t/**\n\t * Get the value of the sensitive attribute\n\t *\n\t * This will decrypt the value using the account's private key\n\t * and return the value as an ArrayBuffer\n\t *\n\t * Since sensitive attributes are binary blobs, this returns an\n\t * ArrayBuffer\n\t */\n\tasync get(): Promise<ArrayBuffer> {\n\t\tconst decryptedValue = await this.#decryptValue(this.#info.encryptedValue);\n\n\t\treturn(bufferToArrayBuffer(decryptedValue));\n\t}\n\n\t/**\n\t * Get the value of the sensitive attribute as a string after being\n\t * interpreted as UTF-8 ( @see SensitiveAttribute.get for more information)\n\t */\n\tasync getString(): Promise<string> {\n\t\tconst value = await this.get();\n\t\treturn(Buffer.from(value).toString('utf-8'));\n\t}\n\n\t/**\n\t * Generate a proof that a sensitive attribute is a given value,\n\t * which can be validated by a third party using the certificate\n\t * and the `validateProof` method\n\t */\n\tasync proove(): Promise<{ value: string; hash: { salt: string }}> {\n\t\tconst value = await this.get();\n\t\tconst salt = await this.#decryptValue(this.#info.hashedValue.encryptedSalt);\n\n\t\treturn({\n\t\t\tvalue: Buffer.from(value).toString('base64'),\n\t\t\thash: {\n\t\t\t\tsalt: salt.toString('base64')\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Validate the proof that a sensitive attribute is a given value\n\t */\n\tasync validateProof(proof: Awaited<ReturnType<this['proove']>>): Promise<boolean> {\n\t\tconst plaintextValue = Buffer.from(proof.value, 'base64');\n\t\tconst proofSaltBuffer = Buffer.from(proof.hash.salt, 'base64');\n\n\t\tconst publicKeyBuffer = Buffer.from(this.#account.publicKey.get());\n\t\tconst encryptedValue = this.#info.encryptedValue;\n\n\t\tconst hashedAndSaltedValue = KeetaNetClient.lib.Utils.Hash.Hash(Buffer.concat([proofSaltBuffer, publicKeyBuffer, encryptedValue, plaintextValue]));\n\t\tconst hashedAndSaltedValueBuffer = Buffer.from(hashedAndSaltedValue);\n\n\t\treturn(this.#info.hashedValue.value.equals(hashedAndSaltedValueBuffer));\n\t}\n\n\ttoJSON(): unknown/* XXX:TODO */ {\n\t\treturn(toJSON(this.#info));\n\t}\n}\n\n/**\n * Database of attributes\n */\nconst CertificateAttributeOIDDB = {\n\t'fullName': '1.3.6.1.4.1.62675.1.0',\n\t'dateOfBirth': '1.3.6.1.4.1.62675.1.1',\n\t'address': '1.3.6.1.4.1.62675.1.2',\n\t'email': '1.3.6.1.4.1.62675.1.3',\n\t'phoneNumber': '1.3.6.1.4.1.62675.1.4'\n};\ntype CertificateAttributeNames = keyof typeof CertificateAttributeOIDDB;\n\ntype BaseCertificateBuilderParams = NonNullable<ConstructorParameters<typeof KeetaNetClient.lib.Utils.Certificate.CertificateBuilder>[0]>;\ntype CertificateBuilderParams = Required<Pick<BaseCertificateBuilderParams, 'issuer' | 'validFrom' | 'validTo' | 'serial' | 'hashLib' | 'issuerDN' | 'subjectDN' | 'isCA'> & {\n\t/**\n\t * The key of the subject -- used for Sensitive Attributes as well\n\t * as the certificate Subject\n\t */\n\tsubject: BaseCertificateBuilderParams['subjectPublicKey'];\n}>;\n\n/**\n * ASN.1 Schema for Certificate KYC Attributes Extension\n *\n * KYCAttributes DEFINITIONS ::= BEGIN\n * KYCAttributes ::= SEQUENCE OF Attribute\n * Attribute ::= SEQUENCE {\n * -- Name of the attribute\n * name OBJECT IDENTIFIER,\n * -- Value of this attribute\n * value CHOICE {\n * -- A plain value, not sensitive\n * plainValue [0] IMPLICIT OCTET STRING,\n * -- A sensitive value, encoded as a SensitiveAttribute in DER encoding\n * sensitiveValue [1] IMPLICIT OCTET STRING\n * }\n * }\n * END\n *\n * https://keeta.notion.site/Keeta-KYC-Certificate-Extensions-13e5da848e588042bdcef81fc40458b7\n *\n */\nconst CertificateKYCAttributeSchemaValidation = {\n\tsequenceOf: [ASN1.ValidateASN1.IsOID, {\n\t\tchoice: [\n\t\t\t{ type: 'context' as const, value: 0 as const, kind: 'implicit' as const, contains: ASN1.ValidateASN1.IsOctetString },\n\t\t\t{ type: 'context' as const, value: 1 as const, kind: 'implicit' as const, contains: ASN1.ValidateASN1.IsOctetString }\n\t\t]\n\t}]\n} satisfies ASN1.Schema;\n\n/** @internal */\ntype CertificateKYCAttributeSchema = ASN1.SchemaMap<typeof CertificateKYCAttributeSchemaValidation>;\n\nexport class CertificateBuilder extends KeetaNetClient.lib.Utils.Certificate.CertificateBuilder {\n\treadonly #attributes: { [name: string]: { sensitive: boolean; value: ArrayBuffer | string }} = {};\n\n\t/**\n\t * Map the parameters from the public interface to the internal\n\t * (Certificate library) interface\n\t */\n\tprivate static mapParams(params?: Partial<CertificateBuilderParams>): Partial<BaseCertificateBuilderParams> {\n\t\tconst paramsCopy = { ...params };\n\t\tlet subjectPublicKey;\n\t\tif (paramsCopy.subject) {\n\t\t\tsubjectPublicKey = paramsCopy.subject;\n\t\t\tdelete(paramsCopy.subject);\n\t\t}\n\t\tconst retval: Partial<BaseCertificateBuilderParams> = paramsCopy;\n\t\tif (subjectPublicKey) {\n\t\t\tretval.subjectPublicKey = subjectPublicKey;\n\t\t}\n\t\treturn(retval);\n\t}\n\n\tconstructor(params?: Partial<CertificateBuilderParams>) {\n\t\tsuper(CertificateBuilder.mapParams(params));\n\t}\n\n\t/**\n\t * Set a KYC Attribute to a given value\n\t */\n\tsetAttribute(name: CertificateAttributeNames, sensitive: boolean, value: ArrayBuffer | string): void {\n\t\tthis.#attributes[name] = { sensitive, value };\n\t}\n\n\tprotected async addExtensions(...args: Parameters<InstanceType<typeof KeetaNetClient.lib.Utils.Certificate.CertificateBuilder>['addExtensions']>): ReturnType<InstanceType<typeof KeetaNetClient.lib.Utils.Certificate.CertificateBuilder>['addExtensions']> {\n\t\tconst retval = await super.addExtensions(...args);\n\n\t\tconst subject = args[0].subjectPublicKey;\n\n\t\t/* Encode the attributes */\n\t\tconst certAttributes: CertificateKYCAttributeSchema = [];\n\t\tfor (const [name, attribute] of Object.entries(this.#attributes)) {\n\t\t\tif (!(name in CertificateAttributeOIDDB)) {\n\t\t\t\tthrow(new Error(`Unknown attribute: ${name}`));\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Since we are iteratively building the certificate, we\n\t\t\t * can assume that the attribute is always present in\n\t\t\t * the object\n\t\t\t */\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tconst nameOID = CertificateAttributeOIDDB[name as keyof typeof CertificateAttributeOIDDB];\n\n\t\t\tlet value: Buffer;\n\t\t\tif (attribute.sensitive) {\n\t\t\t\tconst sensitiveAttribute = new SensitiveAttributeBuilder(subject, attribute.value);\n\t\t\t\tvalue = Buffer.from(await sensitiveAttribute.build());\n\t\t\t} else {\n\t\t\t\tif (typeof attribute.value === 'string') {\n\t\t\t\t\tvalue = Buffer.from(attribute.value, 'utf-8');\n\t\t\t\t} else {\n\t\t\t\t\tvalue = Buffer.from(attribute.value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcertAttributes.push([{\n\t\t\t\ttype: 'oid',\n\t\t\t\toid: nameOID\n\t\t\t}, {\n\t\t\t\ttype: 'context',\n\t\t\t\tkind: 'implicit',\n\t\t\t\tvalue: attribute.sensitive ? 1 : 0,\n\t\t\t\tcontains: value\n\t\t\t}]);\n\t\t}\n\n\t\tif (certAttributes.length > 0) {\n\t\t\tretval.push(\n\t\t\t\tKeetaNetClient.lib.Utils.Certificate.CertificateBuilder.extension('1.3.6.1.4.1.62675.0.0', certAttributes)\n\t\t\t);\n\t\t}\n\n\t\treturn(retval);\n\t}\n\n\t/**\n\t * Create a Certificate object from the builder\n\t *\n\t * The parameters passed in are merged with the parameters passed in\n\t * when constructing the builder\n\t */\n\tasync build(params?: Partial<CertificateBuilderParams>): Promise<Certificate> {\n\t\tconst paramsCopy = CertificateBuilder.mapParams(params);\n\t\tconst certificate = await super.buildDER(paramsCopy);\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-use-before-define\n\t\tconst certificateObject = new Certificate(certificate, {\n\t\t\t/**\n\t\t\t * Specify the moment as `null` to avoid validation\n\t\t\t * of the certificate's validity period. We don't\n\t\t\t * care if the certificate is expired or not for\n\t\t\t * the purposes of this builder.\n\t\t\t */\n\t\t\tmoment: null\n\t\t});\n\n\t\treturn(certificateObject);\n\t}\n}\n\nexport class Certificate extends KeetaNetClient.lib.Utils.Certificate.Certificate {\n\tprivate readonly subjectKey: KeetaNetAccount;\n\tstatic readonly Builder: typeof CertificateBuilder = CertificateBuilder;\n\n\t/**\n\t * User KYC Attributes\n\t */\n\treadonly attributes: {\n\t\t[name: string]: {\n\t\t\tsensitive: true;\n\t\t\tvalue: SensitiveAttribute;\n\t\t} | {\n\t\t\tsensitive: false;\n\t\t\tvalue: ArrayBuffer;\n\t\t}\n\t} = {};\n\n\tconstructor(input: ConstructorParameters<typeof KeetaNetClient.lib.Utils.Certificate.Certificate>[0], options?: ConstructorParameters<typeof KeetaNetClient.lib.Utils.Certificate.Certificate>[1] & { subjectKey?: KeetaNetAccount }) {\n\t\tsuper(input, options);\n\n\t\tthis.subjectKey = options?.subjectKey ?? this.subjectPublicKey;\n\n\t\tsuper.finalizeConstruction();\n\t}\n\n\tprotected finalizeConstruction(): void {\n\t\t/* Do nothing, we call the super method in the constructor */\n\t}\n\n\tprotected processExtension(id: string, value: ArrayBuffer): boolean {\n\t\tif (super.processExtension(id, value)) {\n\t\t\treturn(true);\n\t\t}\n\n\t\tif (id === '1.3.6.1.4.1.62675.0.0') {\n\t\t\tconst attributesRaw = new ASN1.BufferStorageASN1(value, CertificateKYCAttributeSchemaValidation).getASN1();\n\n\t\t\tfor (const attribute of attributesRaw) {\n\t\t\t\tconst name = lookupByOID(attribute[0].oid, CertificateAttributeOIDDB);\n\t\t\t\tconst valueKind = attribute[1].value;\n\t\t\t\tconst value = bufferToArrayBuffer(attribute[1].contains);\n\n\t\t\t\tswitch (valueKind) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\t/* Plain Value */\n\t\t\t\t\t\tthis.attributes[name] = { sensitive: false, value: value };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\t/* Sensitive Value */\n\t\t\t\t\t\tthis.attributes[name] = {\n\t\t\t\t\t\t\tsensitive: true,\n\t\t\t\t\t\t\tvalue: new SensitiveAttribute(this.subjectKey, value)\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tassertNever(valueKind);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn(true);\n\t\t}\n\n\t\treturn(false);\n\t}\n}\n\n/** @internal */\nexport const _Testing = {\n\tSensitiveAttributeBuilder,\n\tSensitiveAttribute\n};\n"]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';
|
|
2
|
+
import { Buffer } from './utils/buffer.js';
|
|
3
|
+
declare const Account: typeof KeetaNetLib.Account;
|
|
4
|
+
type Account = InstanceType<typeof KeetaNetLib.Account>;
|
|
5
|
+
type CipherOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* The symmetric cipher key (if any)
|
|
8
|
+
*/
|
|
9
|
+
cipherKey: Buffer | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* The symmetric cipher IV (if any)
|
|
12
|
+
*/
|
|
13
|
+
cipherIV: Buffer | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* The symmetric cipher algorithm
|
|
16
|
+
*/
|
|
17
|
+
cipherAlgo: string;
|
|
18
|
+
};
|
|
19
|
+
type EncryptedContainerInfo = Pick<CipherOptions, 'cipherAlgo'> & {
|
|
20
|
+
/**
|
|
21
|
+
* Set of accounts which can access the data
|
|
22
|
+
*/
|
|
23
|
+
principals: Account[];
|
|
24
|
+
};
|
|
25
|
+
type UnencryptedContainerInfo = {
|
|
26
|
+
/**
|
|
27
|
+
* Unencrypted container should not have any principals
|
|
28
|
+
*/
|
|
29
|
+
principals: null;
|
|
30
|
+
};
|
|
31
|
+
export declare class EncryptedContainer {
|
|
32
|
+
#private;
|
|
33
|
+
private static readonly algorithm;
|
|
34
|
+
/**
|
|
35
|
+
* Encryption details
|
|
36
|
+
*/
|
|
37
|
+
protected _internalState: EncryptedContainerInfo | UnencryptedContainerInfo;
|
|
38
|
+
constructor(principals: Account[] | null);
|
|
39
|
+
get encrypted(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Create an instance of the EncryptedContainer from an encrypted blob,
|
|
42
|
+
* it will need to be decryptable with one of the specified principals
|
|
43
|
+
*
|
|
44
|
+
* After decryption happens, the list of principals with access to the
|
|
45
|
+
* resource will be reset to what is contained within the encrypted
|
|
46
|
+
* container
|
|
47
|
+
*/
|
|
48
|
+
static fromEncryptedBuffer(data: Buffer, principals: Account[]): EncryptedContainer;
|
|
49
|
+
static fromEncodedBuffer(data: Buffer, principals: Account[] | null): EncryptedContainer;
|
|
50
|
+
/**
|
|
51
|
+
* Create an instance of the EncryptedContainer from a plaintext.
|
|
52
|
+
*
|
|
53
|
+
* It will be decryptable by any one of the specified principals
|
|
54
|
+
*
|
|
55
|
+
* @param data The plaintext data to encrypt or encode
|
|
56
|
+
* @param principals The list of principals who can access the data if it is null then the data is not encrypted
|
|
57
|
+
* @param locked If true, the plaintext data will not be accessible from this instance; otherwise it will be -- default depends on principals
|
|
58
|
+
* @returns The EncryptedContainer instance with the plaintext data and principals set
|
|
59
|
+
*/
|
|
60
|
+
static fromPlaintext(data: string | Buffer, principals: Account[] | null, locked?: boolean): EncryptedContainer;
|
|
61
|
+
/**
|
|
62
|
+
* Set the plaintext buffer to the specified value
|
|
63
|
+
*/
|
|
64
|
+
setPlaintext(data: string | Buffer): void;
|
|
65
|
+
private get _encoded();
|
|
66
|
+
private get _plaintext();
|
|
67
|
+
/**
|
|
68
|
+
* Grant access to the secret for account(s) synchronously. This
|
|
69
|
+
* assumes the plaintext has already been computed and will fail
|
|
70
|
+
* if it is not
|
|
71
|
+
*/
|
|
72
|
+
grantAccessSync(accounts: Account[] | Account): void;
|
|
73
|
+
/**
|
|
74
|
+
* Grant access to the secret for account(s).
|
|
75
|
+
*/
|
|
76
|
+
grantAccess(accounts: Account[] | Account): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Revoke access to the secret for an account synchronously. This
|
|
79
|
+
* assumes the plaintext has already been computed and will fail
|
|
80
|
+
* if it is not
|
|
81
|
+
*/
|
|
82
|
+
revokeAccessSync(account: Account): void;
|
|
83
|
+
/**
|
|
84
|
+
* Revoke access to the secret for an account
|
|
85
|
+
*/
|
|
86
|
+
revokeAccess(account: Account): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Disable access to the plaintext from this instance
|
|
89
|
+
*/
|
|
90
|
+
disablePlaintext(): void;
|
|
91
|
+
/**
|
|
92
|
+
* Get the plaintext for this instance
|
|
93
|
+
*/
|
|
94
|
+
getPlaintext(): Promise<Buffer>;
|
|
95
|
+
/**
|
|
96
|
+
* Get the serializable buffer which can be stored and reconstructed
|
|
97
|
+
*/
|
|
98
|
+
getEncodedBuffer(): Promise<Buffer>;
|
|
99
|
+
/**
|
|
100
|
+
* Get the list of accounts which have access to read the plaintext of
|
|
101
|
+
* this container
|
|
102
|
+
*/
|
|
103
|
+
get principals(): Account[];
|
|
104
|
+
}
|
|
105
|
+
export default EncryptedContainer;
|
|
106
|
+
//# sourceMappingURL=encrypted-container.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypted-container.d.ts","sourceRoot":"","sources":["../../src/lib/encrypted-container.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,IAAI,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAKnE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAO3C,QAAA,MAAM,OAAO,EAAE,OAAO,WAAW,CAAC,OAA6B,CAAC;AAChE,KAAK,OAAO,GAAG,YAAY,CAAC,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;AA0FxD,KAAK,aAAa,GAAG;IACpB;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACnB,CAAA;AA0TD,KAAK,sBAAsB,GAAG,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,GAAG;IACjE;;OAEG;IACH,UAAU,EAAE,OAAO,EAAE,CAAC;CACtB,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC/B;;OAEG;IACH,UAAU,EAAE,IAAI,CAAC;CACjB,CAAA;AAED,qBAAa,kBAAkB;;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAOlD;;OAEG;IACH,SAAS,CAAC,cAAc,EAAE,sBAAsB,GAAG,wBAAwB,CAAC;gBAUhE,UAAU,EAAE,OAAO,EAAE,GAAG,IAAI;IAcxC,IAAI,SAAS,IAAI,OAAO,CAEvB;IAMD;;;;;;;OAOG;IACH,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,kBAAkB;IASnF,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,IAAI,GAAG,kBAAkB;IASxF;;;;;;;;;OASG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,kBAAkB;IAmB/G;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAezC,OAAO,KAAK,QAAQ,GAMnB;IAED,OAAO,KAAK,UAAU,GAMrB;IA8JD;;;;OAIG;IACH,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,GAAG,IAAI;IAmBpD;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/D;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAiBxC;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnD;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAIxB;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAmBrC;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAezC;;;OAGG;IACH,IAAI,UAAU,IAAI,OAAO,EAAE,CAM1B;CACD;AAQD,eAAe,kBAAkB,CAAC"}
|