@keetanetwork/anchor 0.0.45 → 0.0.48

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.
Files changed (82) hide show
  1. package/LICENSE +163 -34
  2. package/lib/asset.d.ts +30 -0
  3. package/lib/asset.d.ts.map +1 -0
  4. package/lib/asset.js +78 -0
  5. package/lib/asset.js.map +1 -0
  6. package/lib/certificates.d.ts +11 -38
  7. package/lib/certificates.d.ts.map +1 -1
  8. package/lib/certificates.js +33 -336
  9. package/lib/certificates.js.map +1 -1
  10. package/lib/resolver.d.ts +9 -2
  11. package/lib/resolver.d.ts.map +1 -1
  12. package/lib/resolver.js +195 -159
  13. package/lib/resolver.js.map +1 -1
  14. package/lib/sensitive-attribute.d.ts +87 -0
  15. package/lib/sensitive-attribute.d.ts.map +1 -0
  16. package/lib/sensitive-attribute.js +419 -0
  17. package/lib/sensitive-attribute.js.map +1 -0
  18. package/lib/token-metadata.d.ts +21 -0
  19. package/lib/token-metadata.d.ts.map +1 -0
  20. package/lib/token-metadata.generated.d.ts +5 -0
  21. package/lib/token-metadata.generated.d.ts.map +1 -0
  22. package/lib/token-metadata.generated.js +70 -0
  23. package/lib/token-metadata.generated.js.map +1 -0
  24. package/lib/token-metadata.js +57 -0
  25. package/lib/token-metadata.js.map +1 -0
  26. package/lib/utils/pii.d.ts +128 -0
  27. package/lib/utils/pii.d.ts.map +1 -0
  28. package/lib/utils/pii.js +198 -0
  29. package/lib/utils/pii.js.map +1 -0
  30. package/npm-shrinkwrap.json +2 -2
  31. package/package.json +1 -1
  32. package/services/asset-movement/common.d.ts +7 -29
  33. package/services/asset-movement/common.d.ts.map +1 -1
  34. package/services/asset-movement/common.js +5223 -2660
  35. package/services/asset-movement/common.js.map +1 -1
  36. package/services/asset-movement/lib/data/addresses/bank-account/iban-swift.d.ts.map +1 -1
  37. package/services/asset-movement/lib/data/addresses/bank-account/iban-swift.js +22 -1
  38. package/services/asset-movement/lib/data/addresses/bank-account/iban-swift.js.map +1 -1
  39. package/services/asset-movement/lib/data/addresses/bank-account/interac.d.ts +1 -1
  40. package/services/asset-movement/lib/data/addresses/bank-account/interac.d.ts.map +1 -1
  41. package/services/asset-movement/lib/data/addresses/bank-account/interac.js +13 -3
  42. package/services/asset-movement/lib/data/addresses/bank-account/interac.js.map +1 -1
  43. package/services/asset-movement/lib/data/addresses/bank-account/pix.d.ts +1 -1
  44. package/services/asset-movement/lib/data/addresses/bank-account/pix.d.ts.map +1 -1
  45. package/services/asset-movement/lib/data/addresses/bank-account/pix.js +11 -1
  46. package/services/asset-movement/lib/data/addresses/bank-account/pix.js.map +1 -1
  47. package/services/asset-movement/lib/data/addresses/types.generated.d.ts +116 -33
  48. package/services/asset-movement/lib/data/addresses/types.generated.d.ts.map +1 -1
  49. package/services/asset-movement/lib/data/addresses/types.generated.js +102 -26
  50. package/services/asset-movement/lib/data/addresses/types.generated.js.map +1 -1
  51. package/services/asset-movement/lib/data/types.d.ts.map +1 -1
  52. package/services/asset-movement/lib/data/types.js +15 -10
  53. package/services/asset-movement/lib/data/types.js.map +1 -1
  54. package/services/fx/client.d.ts.map +1 -1
  55. package/services/fx/client.js +6 -2
  56. package/services/fx/client.js.map +1 -1
  57. package/services/fx/common.d.ts +14 -6
  58. package/services/fx/common.d.ts.map +1 -1
  59. package/services/fx/common.js +34 -8
  60. package/services/fx/common.js.map +1 -1
  61. package/services/fx/server.d.ts +6 -0
  62. package/services/fx/server.d.ts.map +1 -1
  63. package/services/fx/server.js +52 -10
  64. package/services/fx/server.js.map +1 -1
  65. package/services/kyc/common.d.ts +7 -0
  66. package/services/kyc/common.d.ts.map +1 -1
  67. package/services/kyc/common.generated.js +6 -1
  68. package/services/kyc/common.generated.js.map +1 -1
  69. package/services/kyc/common.js.map +1 -1
  70. package/services/notification/client.d.ts +1 -1
  71. package/services/notification/client.d.ts.map +1 -1
  72. package/services/notification/client.js +65 -2
  73. package/services/notification/client.js.map +1 -1
  74. package/services/notification/common.d.ts +1 -0
  75. package/services/notification/common.d.ts.map +1 -1
  76. package/services/notification/common.js.map +1 -1
  77. package/services/storage/clients/contacts.generated.js +506 -233
  78. package/services/storage/clients/contacts.generated.js.map +1 -1
  79. package/services/storage/server.d.ts +8 -1
  80. package/services/storage/server.d.ts.map +1 -1
  81. package/services/storage/server.js +9 -1
  82. package/services/storage/server.js.map +1 -1
@@ -1,19 +1,15 @@
1
1
  import * as KeetaNetClient from '@keetanetwork/keetanet-client';
2
2
  import * as oids from '../services/kyc/oids.generated.js';
3
3
  import * as ASN1 from './utils/asn1.js';
4
- import { arrayBufferLikeToBuffer, arrayBufferToBuffer, Buffer, bufferToArrayBuffer } from './utils/buffer.js';
5
- import crypto from './utils/crypto.js';
4
+ import { arrayBufferToBuffer, Buffer, bufferToArrayBuffer } from './utils/buffer.js';
6
5
  import { assertNever } from './utils/never.js';
7
6
  import { CertificateAttributeOIDDB, CertificateAttributeSchema } from '../services/kyc/iso20022.generated.js';
8
- import { getOID, lookupByOID } from './utils/oid.js';
9
- import { toJSONSerializable } from './utils/json.js';
7
+ import { lookupByOID } from './utils/oid.js';
10
8
  import { EncryptedContainer } from './encrypted-container.js';
11
9
  import { assertSharableCertificateAttributesContentsSchema } from './certificates.generated.js';
12
10
  import { checkHashWithOID } from './utils/external.js';
13
- /**
14
- * Short alias for printing a debug representation of an object
15
- */
16
- const DPO = KeetaNetClient.lib.Utils.Helper.debugPrintableObject.bind(KeetaNetClient.lib.Utils.Helper);
11
+ import { SensitiveAttribute, encodeForSensitive, encodeAttribute } from './sensitive-attribute.js';
12
+ export { SensitiveAttribute } from './sensitive-attribute.js';
17
13
  /**
18
14
  * Short alias for the KeetaNetAccount type
19
15
  */
@@ -180,9 +176,6 @@ async function walkObject(input, keyTransformer) {
180
176
  }
181
177
  return (newObj);
182
178
  }
183
- function toJSON(data) {
184
- return (toJSONSerializable(data));
185
- }
186
179
  // Generic type guard to align decoded values with generated attribute types
187
180
  function isAttributeValue(_name, _v) {
188
181
  // Runtime schema validation is already performed by BufferStorageASN1; this guard
@@ -196,57 +189,6 @@ function asAttributeValue(name, v) {
196
189
  }
197
190
  return (v);
198
191
  }
199
- /**
200
- * Sensitive Attribute Schema
201
- *
202
- * ASN.1 Schema:
203
- * SensitiveAttributes DEFINITIONS ::= BEGIN
204
- * SensitiveAttribute ::= SEQUENCE {
205
- * version INTEGER { v1(0) },
206
- * cipher SEQUENCE {
207
- * algorithm OBJECT IDENTIFIER,
208
- * ivOrNonce OCTET STRING,
209
- * key OCTET STRING
210
- * },
211
- * hashedValue SEQUENCE {
212
- * encryptedSalt OCTET STRING,
213
- * algorithm OBJECT IDENTIFIER,
214
- * value OCTET STRING
215
- * },
216
- * encryptedValue OCTET STRING
217
- * }
218
- * END
219
- *
220
- * https://keeta.notion.site/Keeta-KYC-Certificate-Extensions-13e5da848e588042bdcef81fc40458b7
221
- *
222
- * @internal
223
- */
224
- const SensitiveAttributeSchemaInternal = [
225
- 0n,
226
- [
227
- ASN1.ValidateASN1.IsOID,
228
- ASN1.ValidateASN1.IsOctetString,
229
- ASN1.ValidateASN1.IsOctetString
230
- ],
231
- [
232
- ASN1.ValidateASN1.IsOctetString,
233
- ASN1.ValidateASN1.IsOID,
234
- ASN1.ValidateASN1.IsOctetString
235
- ],
236
- ASN1.ValidateASN1.IsOctetString
237
- ];
238
- /*
239
- * Database of permitted algorithms and their OIDs
240
- */
241
- const sensitiveAttributeOIDDB = {
242
- 'aes-256-gcm': oids.AES_256_GCM,
243
- 'aes-256-cbc': oids.AES_256_CBC,
244
- 'sha2-256': oids.SHA2_256,
245
- 'sha3-256': oids.SHA3_256,
246
- 'sha256': oids.SHA2_256,
247
- 'aes256-gcm': oids.AES_256_GCM,
248
- 'aes256-cbc': oids.AES_256_CBC
249
- };
250
192
  function assertCertificateAttributeNames(name) {
251
193
  if (!(name in CertificateAttributeOIDDB)) {
252
194
  throw (new Error(`Unknown attribute name: ${name}`));
@@ -256,50 +198,6 @@ function asCertificateAttributeNames(name) {
256
198
  assertCertificateAttributeNames(name);
257
199
  return (name);
258
200
  }
259
- function encodeAttribute(name, value) {
260
- const schema = CertificateAttributeSchema[name];
261
- let encodedJS;
262
- try {
263
- encodedJS = new ASN1.ValidateASN1(schema).fromJavaScriptObject(value);
264
- }
265
- catch (err) {
266
- const message = err instanceof Error ? err.message : String(err);
267
- throw (new Error(`Attribute ${name}: ${message} (value: ${JSON.stringify(DPO(value))})`));
268
- }
269
- if (encodedJS === undefined) {
270
- throw (new Error(`Unsupported attribute value for encoding: ${JSON.stringify(DPO(value))}`));
271
- }
272
- const asn1Object = ASN1.JStoASN1(encodedJS);
273
- if (!asn1Object) {
274
- throw (new Error(`Failed to encode value for attribute ${name}`));
275
- }
276
- return (asn1Object.toBER(false));
277
- }
278
- // Prepare a value for inclusion in a SensitiveAttribute: pre-encode complex and date types
279
- function encodeForSensitive(name, value) {
280
- if (Buffer.isBuffer(value)) {
281
- return (value);
282
- }
283
- if (value instanceof ArrayBuffer) {
284
- return (arrayBufferToBuffer(value));
285
- }
286
- if (typeof value === 'string') {
287
- const asn1 = ASN1.JStoASN1({ type: 'string', kind: 'utf8', value });
288
- return (arrayBufferToBuffer(asn1.toBER(false)));
289
- }
290
- if (value instanceof Date) {
291
- const asn1 = ASN1.JStoASN1(value);
292
- return (arrayBufferToBuffer(asn1.toBER(false)));
293
- }
294
- if (typeof value === 'object' && value !== null) {
295
- if (!name) {
296
- throw (new Error('attributeName required for complex types'));
297
- }
298
- const encoded = encodeAttribute(name, value);
299
- return (arrayBufferToBuffer(encoded));
300
- }
301
- return (Buffer.from(String(value), 'utf-8'));
302
- }
303
201
  function unwrapSingleLayer(schema) {
304
202
  if (typeof schema === 'object' && schema !== null && 'type' in schema && schema.type === 'context') {
305
203
  return (schema.contains);
@@ -438,216 +336,6 @@ async function decodeAttribute(name, value, principals) {
438
336
  const candidate = normalizeDecodedASN1(plainObject, principals);
439
337
  return (asAttributeValue(name, candidate));
440
338
  }
441
- class SensitiveAttributeBuilder {
442
- #account;
443
- #value;
444
- constructor(account) {
445
- this.#account = account;
446
- }
447
- set(value) {
448
- this.#value = Buffer.isBuffer(value) ? value : arrayBufferLikeToBuffer(value);
449
- return (this);
450
- }
451
- async build() {
452
- if (this.#value === undefined) {
453
- throw (new Error('Value not set'));
454
- }
455
- const salt = crypto.randomBytes(32);
456
- const hashingAlgorithm = KeetaNetClient.lib.Utils.Hash.HashFunctionName;
457
- const publicKey = Buffer.from(this.#account.publicKey.get());
458
- const cipher = 'aes-256-gcm';
459
- const key = crypto.randomBytes(32);
460
- const nonce = crypto.randomBytes(12);
461
- const encryptedKey = await this.#account.encrypt(bufferToArrayBuffer(key));
462
- function encrypt(value) {
463
- const cipherObject = crypto.createCipheriv(cipher, key, nonce);
464
- let retval = cipherObject.update(value);
465
- retval = Buffer.concat([retval, cipherObject.final()]);
466
- /*
467
- * For AES-GCM, the last 16 bytes are the authentication tag
468
- */
469
- if (cipher === 'aes-256-gcm') {
470
- const getAuthTagFn = Reflect.get(cipherObject, 'getAuthTag');
471
- if (typeof getAuthTagFn === 'function') {
472
- const tag = getAuthTagFn.call(cipherObject);
473
- if (!Buffer.isBuffer(tag)) {
474
- throw (new Error('getAuthTag did not return a Buffer'));
475
- }
476
- retval = Buffer.concat([retval, tag]);
477
- }
478
- else {
479
- throw (new Error('getAuthTag is not available on cipherObject'));
480
- }
481
- }
482
- return (retval);
483
- }
484
- const encryptedValue = encrypt(this.#value);
485
- const encryptedSalt = encrypt(arrayBufferLikeToBuffer(salt));
486
- const saltedValue = Buffer.concat([salt, publicKey, encryptedValue, this.#value]);
487
- const hashedAndSaltedValue = KeetaNetClient.lib.Utils.Hash.Hash(saltedValue);
488
- const attributeStructure = [
489
- /* Version */
490
- 0n,
491
- /* Cipher Details */
492
- [
493
- /* Algorithm */
494
- { type: 'oid', oid: getOID(cipher, sensitiveAttributeOIDDB) },
495
- /* IV or Nonce */
496
- nonce,
497
- /* Symmetric key, encrypted with the public key of the account */
498
- Buffer.from(encryptedKey)
499
- ],
500
- /* Hashed Value */
501
- [
502
- /* Encrypted Salt */
503
- Buffer.from(encryptedSalt),
504
- /* Hashing Algorithm */
505
- { type: 'oid', oid: getOID(hashingAlgorithm, sensitiveAttributeOIDDB) },
506
- /* Hash of <Encrypted Salt> || <Public Key> || <Value> */
507
- Buffer.from(hashedAndSaltedValue)
508
- ],
509
- /* Encrypted Value, encrypted with the Cipher above */
510
- encryptedValue
511
- ];
512
- const encodedAttributeObject = ASN1.JStoASN1(attributeStructure);
513
- // Produce canonical DER as ArrayBuffer
514
- const retval = encodedAttributeObject.toBER(false);
515
- return (retval);
516
- }
517
- }
518
- class SensitiveAttribute {
519
- #account;
520
- #info;
521
- #decoder;
522
- constructor(account, data, decoder) {
523
- this.#account = account;
524
- this.#info = this.decode(data);
525
- if (decoder) {
526
- this.#decoder = decoder;
527
- }
528
- }
529
- decode(data) {
530
- if (Buffer.isBuffer(data)) {
531
- data = bufferToArrayBuffer(data);
532
- }
533
- let decodedAttribute;
534
- try {
535
- const dataObject = new ASN1.BufferStorageASN1(data, SensitiveAttributeSchemaInternal);
536
- decodedAttribute = dataObject.getASN1();
537
- }
538
- catch {
539
- const js = ASN1.ASN1toJS(data);
540
- throw (new Error(`SensitiveAttribute.decode: unexpected DER shape ${JSON.stringify(DPO(js))}`));
541
- }
542
- const decodedVersion = decodedAttribute[0] + 1n;
543
- if (decodedVersion !== 1n) {
544
- throw (new Error(`Unsupported Sensitive Attribute version (${decodedVersion})`));
545
- }
546
- return ({
547
- version: decodedVersion,
548
- publicKey: this.#account.publicKeyString.get(),
549
- cipher: {
550
- algorithm: lookupByOID(decodedAttribute[1][0].oid, sensitiveAttributeOIDDB),
551
- iv: decodedAttribute[1][1],
552
- key: decodedAttribute[1][2]
553
- },
554
- hashedValue: {
555
- encryptedSalt: decodedAttribute[2][0],
556
- algorithm: lookupByOID(decodedAttribute[2][1].oid, sensitiveAttributeOIDDB),
557
- value: decodedAttribute[2][2]
558
- },
559
- encryptedValue: decodedAttribute[3]
560
- });
561
- }
562
- async #decryptValue(value) {
563
- const decryptedKey = await this.#account.decrypt(bufferToArrayBuffer(this.#info.cipher.key));
564
- const algorithm = this.#info.cipher.algorithm;
565
- const iv = this.#info.cipher.iv;
566
- const cipher = crypto.createDecipheriv(algorithm, Buffer.from(decryptedKey), iv);
567
- // For AES-GCM, the last 16 bytes are the authentication tag
568
- if (algorithm === 'aes-256-gcm') {
569
- const authTag = value.subarray(value.length - 16);
570
- const ciphertext = value.subarray(0, value.length - 16);
571
- // XXX:TODO Fix typescript unsafe calls
572
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
573
- const setAuthTagFn = Reflect.get(cipher, 'setAuthTag');
574
- if (typeof setAuthTagFn === 'function') {
575
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
576
- setAuthTagFn.call(cipher, authTag);
577
- }
578
- else {
579
- throw (new Error('setAuthTag is not available on cipher'));
580
- }
581
- const decrypted = cipher.update(ciphertext);
582
- cipher.final(); // Verify auth tag
583
- return (decrypted);
584
- }
585
- // For other algorithms (like CBC), just decrypt normally
586
- const decryptedValue = cipher.update(value);
587
- cipher.final();
588
- return (decryptedValue);
589
- }
590
- /**
591
- * Get the value of the sensitive attribute
592
- *
593
- * This will decrypt the value using the account's private key
594
- * and return the value as an ArrayBuffer
595
- *
596
- * Since sensitive attributes are binary blobs, this returns an
597
- * ArrayBuffer
598
- */
599
- async get() {
600
- const decryptedValue = await this.#decryptValue(arrayBufferLikeToBuffer(this.#info.encryptedValue));
601
- return (bufferToArrayBuffer(decryptedValue));
602
- }
603
- async getValue() {
604
- const value = await this.get();
605
- if (!this.#decoder) {
606
- /**
607
- * TypeScript complains that T may not be the correct
608
- * type here, but gives us no tools to enforce that it
609
- * is -- it should always be ArrayBuffer if no decoder
610
- * is provided, but someone could always specify a
611
- * type parameter in that case and we cannot check
612
- * that at runtime since T is only a compile-time type.
613
- */
614
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
615
- return value;
616
- }
617
- return (this.#decoder(value));
618
- }
619
- /**
620
- * Generate a proof that a sensitive attribute is a given value,
621
- * which can be validated by a third party using the certificate
622
- * and the `validateProof` method
623
- */
624
- async getProof() {
625
- const value = await this.get();
626
- const salt = await this.#decryptValue(arrayBufferLikeToBuffer(this.#info.hashedValue.encryptedSalt));
627
- return ({
628
- value: Buffer.from(value).toString('base64'),
629
- hash: {
630
- salt: salt.toString('base64')
631
- }
632
- });
633
- }
634
- /**
635
- * Validate the proof that a sensitive attribute is a given value
636
- */
637
- async validateProof(proof) {
638
- const plaintextValue = Buffer.from(proof.value, 'base64');
639
- const proofSaltBuffer = Buffer.from(proof.hash.salt, 'base64');
640
- const publicKeyBuffer = Buffer.from(this.#account.publicKey.get());
641
- const encryptedValue = this.#info.encryptedValue;
642
- const hashInput = Buffer.concat([proofSaltBuffer, publicKeyBuffer, encryptedValue, plaintextValue]);
643
- const hashedAndSaltedValue = KeetaNetClient.lib.Utils.Hash.Hash(hashInput);
644
- const hashedAndSaltedValueBuffer = Buffer.from(hashedAndSaltedValue);
645
- return (this.#info.hashedValue.value.equals(hashedAndSaltedValueBuffer));
646
- }
647
- toJSON() {
648
- return (toJSON(this.#info));
649
- }
650
- }
651
339
  /**
652
340
  * ASN.1 Schema for Certificate KYC Attributes Extension
653
341
  *
@@ -679,6 +367,7 @@ const CertificateKYCAttributeSchemaValidation = {
679
367
  };
680
368
  export class CertificateBuilder extends BaseCertificateBuilder {
681
369
  #attributes = {};
370
+ #subjectPublicKeyString;
682
371
  /**
683
372
  * Map the parameters from the public interface to the internal
684
373
  * (Certificate library) interface
@@ -698,6 +387,9 @@ export class CertificateBuilder extends BaseCertificateBuilder {
698
387
  }
699
388
  constructor(params) {
700
389
  super(CertificateBuilder.mapParams(params));
390
+ if (params?.subject) {
391
+ this.#subjectPublicKeyString = params.subject.publicKeyString.get();
392
+ }
701
393
  }
702
394
  /**
703
395
  * Set a KYC Attribute to a given value.
@@ -708,14 +400,12 @@ export class CertificateBuilder extends BaseCertificateBuilder {
708
400
  * value can be proven later without revealing it.
709
401
  */
710
402
  setAttribute(name, sensitive, value) {
711
- // Non-sensitive path: only primitive schema (string/date) allowed
712
403
  const schemaValidator = CertificateAttributeSchema[name];
713
404
  let encoded;
714
405
  if (value instanceof ArrayBuffer) {
715
406
  encoded = value;
716
407
  }
717
408
  else if (name in CertificateAttributeSchema) {
718
- /* XXX: Why do we have two encoding methods ? */
719
409
  encoded = bufferToArrayBuffer(encodeForSensitive(name, value));
720
410
  }
721
411
  else if (schemaValidator === ASN1.ValidateASN1.IsDate) {
@@ -728,42 +418,50 @@ export class CertificateBuilder extends BaseCertificateBuilder {
728
418
  encoded = encodeAttribute(name, value);
729
419
  }
730
420
  else {
731
- throw (new Error('Unsupported non-sensitive value type'));
421
+ throw (new Error('Unsupported attribute value type'));
732
422
  }
733
423
  this.#attributes[name] = {
734
424
  sensitive: sensitive,
735
425
  value: encoded
736
426
  };
737
427
  }
428
+ /**
429
+ * Set a pre-built SensitiveAttribute for a given attribute name.
430
+ *
431
+ * The attribute must have been encrypted for this certificate's subject.
432
+ *
433
+ * @throws Error if the attribute was encrypted for a different subject
434
+ */
435
+ setSensitiveAttribute(name, attribute) {
436
+ if (this.#subjectPublicKeyString && attribute.publicKey !== this.#subjectPublicKeyString) {
437
+ throw (new Error('SensitiveAttribute was encrypted for a different subject'));
438
+ }
439
+ this.#attributes[name] = {
440
+ sensitive: true,
441
+ attribute
442
+ };
443
+ }
738
444
  async addExtensions(...args) {
739
445
  const retval = await super.addExtensions(...args);
740
- const subject = args[0].subjectPublicKey;
741
446
  /* Encode the attributes */
742
447
  const certAttributes = [];
743
448
  for (const [name, attribute] of Object.entries(this.#attributes)) {
744
449
  if (!(name in CertificateAttributeOIDDB)) {
745
450
  throw (new Error(`Unknown attribute: ${name}`));
746
451
  }
747
- /*
748
- * Since we are iteratively building the certificate, we
749
- * can assume that the attribute is always present in
750
- * the object
751
- */
752
452
  assertCertificateAttributeNames(name);
753
453
  const nameOID = CertificateAttributeOIDDB[name];
754
454
  let value;
755
- if (attribute.sensitive) {
756
- const builder = new SensitiveAttributeBuilder(subject);
757
- builder.set(attribute.value);
758
- value = arrayBufferToBuffer(await builder.build());
455
+ if ('attribute' in attribute) {
456
+ value = arrayBufferToBuffer(attribute.attribute.toDER());
457
+ }
458
+ else if (attribute.sensitive) {
459
+ const subject = args[0].subjectPublicKey;
460
+ const sensitiveAttr = await SensitiveAttribute.create(subject, name, attribute.value);
461
+ value = arrayBufferToBuffer(sensitiveAttr.toDER());
759
462
  }
760
463
  else {
761
- if (typeof attribute.value === 'string') {
762
- value = Buffer.from(attribute.value, 'utf-8');
763
- }
764
- else {
765
- value = arrayBufferToBuffer(attribute.value);
766
- }
464
+ value = arrayBufferToBuffer(attribute.value);
767
465
  }
768
466
  certAttributes.push([{
769
467
  type: 'oid',
@@ -1297,7 +995,6 @@ export class SharableCertificateAttributes {
1297
995
  Certificate.SharableAttributes = SharableCertificateAttributes;
1298
996
  /** @internal */
1299
997
  export const _Testing = {
1300
- SensitiveAttributeBuilder,
1301
998
  SensitiveAttribute,
1302
999
  ValidateASN1: ASN1.ValidateASN1,
1303
1000
  BufferStorageASN1: ASN1.BufferStorageASN1,