@noz-ele/edgca 0.2.0 → 0.4.0

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/dist/bytes.d.ts CHANGED
@@ -6,4 +6,5 @@ export declare function bytesToBinary(bytes: Uint8Array): string;
6
6
  export declare function binaryToBytes(binary: string): Uint8Array;
7
7
  export declare function cloneBytes(bytes: Uint8Array): Uint8Array;
8
8
  export declare function arrayBufferFromBytes(bytes: Uint8Array): ArrayBuffer;
9
+ export declare function randomBytes(length: number): Uint8Array;
9
10
  //# sourceMappingURL=bytes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,CAWpE;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAWhE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAEnD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAYpD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAUvD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAQxD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAExD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAInE"}
1
+ {"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,CAWpE;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAWhE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAEnD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAYpD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAUvD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAQxD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAExD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAInE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAItD"}
package/dist/bytes.js CHANGED
@@ -56,3 +56,8 @@ export function arrayBufferFromBytes(bytes) {
56
56
  copy.set(bytes);
57
57
  return copy.buffer;
58
58
  }
59
+ export function randomBytes(length) {
60
+ const bytes = new Uint8Array(length);
61
+ crypto.getRandomValues(bytes);
62
+ return bytes;
63
+ }
package/dist/ca.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import type { CertificateAuthority, CreateRootCAOptions, ImportCertificateAuthorityOptions, IssueClientCertForPublicKeyOptions, IssueClientCertOptions, IssueIntermediateCAOptions, IssuedClientCertificate, IssuedClientCertificateForPublicKey } from "./types.js";
1
+ import type { CertificateAuthority, CreateRootCAOptions, ImportCertificateAuthorityOptions, IssueClientCertForPublicKeyOptions, IssueClientCertOptions, IssueDocumentSigningCertOptions, IssueIntermediateCAOptions, IssuedClientCertificate, IssuedClientCertificateForPublicKey, IssuedDocumentSigningCertificate } from "./types.js";
2
2
  export declare function createRootCA(options: CreateRootCAOptions): Promise<CertificateAuthority>;
3
3
  export declare function issueIntermediateCA(options: IssueIntermediateCAOptions): Promise<CertificateAuthority>;
4
4
  export declare function issueClientCert(options: IssueClientCertOptions): Promise<IssuedClientCertificate>;
5
5
  export declare function issueClientCertForPublicKey(options: IssueClientCertForPublicKeyOptions): Promise<IssuedClientCertificateForPublicKey>;
6
+ export declare function issueDocumentSigningCert(options: IssueDocumentSigningCertOptions): Promise<IssuedDocumentSigningCertificate>;
6
7
  export declare function importCertificateAuthority(options: ImportCertificateAuthorityOptions): Promise<CertificateAuthority>;
7
8
  //# sourceMappingURL=ca.d.ts.map
package/dist/ca.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ca.d.ts","sourceRoot":"","sources":["../src/ca.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,iCAAiC,EACjC,kCAAkC,EAClC,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACvB,mCAAmC,EAEpC,MAAM,YAAY,CAAC;AAapB,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0B9F;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgC5G;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAqBvG;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,kCAAkC,GAC1C,OAAO,CAAC,mCAAmC,CAAC,CAkB9C;AAuDD,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,iCAAiC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAe1H"}
1
+ {"version":3,"file":"ca.d.ts","sourceRoot":"","sources":["../src/ca.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,iCAAiC,EACjC,kCAAkC,EAClC,sBAAsB,EACtB,+BAA+B,EAC/B,0BAA0B,EAC1B,uBAAuB,EACvB,mCAAmC,EACnC,gCAAgC,EAEjC,MAAM,YAAY,CAAC;AAcpB,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0B9F;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgC5G;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAoBvG;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,kCAAkC,GAC1C,OAAO,CAAC,mCAAmC,CAAC,CAiB9C;AAuED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,gCAAgC,CAAC,CAoB3C;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,iCAAiC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAe1H"}
package/dist/ca.js CHANGED
@@ -3,7 +3,7 @@ import { assertKeyPairMatches, curveOf, exportSpki, generateKeyPair, keyIdentifi
3
3
  import { encodeName } from "./name.js";
4
4
  import { certificateToPem, pemToDer, pemToDerWithLabel, splitPemBlocks } from "./pem.js";
5
5
  import { parseCertificateDer } from "./parser.js";
6
- import { authorityKeyIdentifierExtension, basicConstraintsCaExtension, basicConstraintsLeafExtension, buildCertificate, buildTbsCertificate, extendedKeyUsageClientAuthExtension, keyUsageExtension, subjectAltNameExtension, subjectKeyIdentifierExtension } from "./x509.js";
6
+ import { authorityKeyIdentifierExtension, basicConstraintsCaExtension, basicConstraintsLeafExtension, buildCertificate, buildTbsCertificate, extendedKeyUsageClientAuthExtension, extendedKeyUsageDocumentSigningExtension, keyUsageExtension, subjectAltNameExtension, subjectKeyIdentifierExtension } from "./x509.js";
7
7
  export async function createRootCA(options) {
8
8
  const keyPair = await resolveKeyPair(options.keyPair);
9
9
  const issuerCurve = curveOf(keyPair.privateKey);
@@ -65,14 +65,12 @@ export async function issueIntermediateCA(options) {
65
65
  }
66
66
  export async function issueClientCert(options) {
67
67
  const keyPair = await generateKeyPair();
68
- const built = await buildClientCertificate(options.ca, keyPair.publicKey, {
68
+ const built = await buildLeafCertificate(options.ca, keyPair.publicKey, {
69
69
  subject: options.subject,
70
70
  days: options.days,
71
71
  notBefore: options.notBefore,
72
- serialNumber: options.serialNumber,
73
- dnsNames: options.dnsNames,
74
- ipAddresses: options.ipAddresses
75
- });
72
+ serialNumber: options.serialNumber
73
+ }, clientCertProfileExtensions(options.dnsNames, options.ipAddresses));
76
74
  return {
77
75
  certPem: built.certPem,
78
76
  certDer: built.certDer,
@@ -82,42 +80,36 @@ export async function issueClientCert(options) {
82
80
  };
83
81
  }
84
82
  export async function issueClientCertForPublicKey(options) {
85
- const built = await buildClientCertificate(options.ca, options.publicKey, {
83
+ const built = await buildLeafCertificate(options.ca, options.publicKey, {
86
84
  subject: options.subject,
87
85
  days: options.days,
88
86
  notBefore: options.notBefore,
89
- serialNumber: options.serialNumber,
90
- dnsNames: options.dnsNames,
91
- ipAddresses: options.ipAddresses
92
- });
87
+ serialNumber: options.serialNumber
88
+ }, clientCertProfileExtensions(options.dnsNames, options.ipAddresses));
93
89
  return {
94
90
  certPem: built.certPem,
95
91
  certDer: built.certDer,
96
92
  certChainPem: built.certChainPem
97
93
  };
98
94
  }
99
- async function buildClientCertificate(ca, subjectPublicKey, content) {
95
+ async function buildLeafCertificate(ca, subjectPublicKey, identity, profileExtensions) {
100
96
  const issuer = await parseIssuer(ca);
101
97
  const issuerChainPem = ca.issuerChainPem;
102
98
  assertCanIssueCertificate(issuer);
103
99
  const issuerCurve = curveOf(ca.privateKey);
104
- const subjectNameDer = encodeName(content.subject);
100
+ const subjectNameDer = encodeName(identity.subject);
105
101
  const spki = await exportSpki(subjectPublicKey);
106
102
  const subjectKeyIdentifier = await keyIdentifierFromSpki(spki);
107
103
  const authorityKeyIdentifier = issuer.subjectKeyIdentifier ?? await keyIdentifierFromSpki(issuer.subjectPublicKeyInfoDer);
108
- const san = subjectAltNameExtension(content.dnsNames, content.ipAddresses);
109
104
  const extensions = [
110
- basicConstraintsLeafExtension(),
111
- keyUsageExtension(["digitalSignature"]),
112
- extendedKeyUsageClientAuthExtension(),
105
+ ...profileExtensions,
113
106
  subjectKeyIdentifierExtension(subjectKeyIdentifier),
114
- authorityKeyIdentifierExtension(authorityKeyIdentifier),
115
- ...(san ? [san] : [])
107
+ authorityKeyIdentifierExtension(authorityKeyIdentifier)
116
108
  ];
117
109
  const { tbsCertificateDer } = buildTbsCertificate({
118
- serialNumber: content.serialNumber,
119
- notBefore: content.notBefore,
120
- days: content.days,
110
+ serialNumber: identity.serialNumber,
111
+ notBefore: identity.notBefore,
112
+ days: identity.days,
121
113
  issuerNameDer: issuer.subjectNameDer,
122
114
  subjectNameDer,
123
115
  subjectPublicKeyInfoDer: spki,
@@ -133,6 +125,38 @@ async function buildClientCertificate(ca, subjectPublicKey, content) {
133
125
  certChainPem: joinPemChain([certPem, ca.certPem, issuerChainPem])
134
126
  };
135
127
  }
128
+ function clientCertProfileExtensions(dnsNames, ipAddresses) {
129
+ const san = subjectAltNameExtension(dnsNames, ipAddresses);
130
+ return [
131
+ basicConstraintsLeafExtension(),
132
+ keyUsageExtension(["digitalSignature"]),
133
+ extendedKeyUsageClientAuthExtension(),
134
+ ...(san ? [san] : [])
135
+ ];
136
+ }
137
+ function documentSigningProfileExtensions() {
138
+ return [
139
+ basicConstraintsLeafExtension(),
140
+ keyUsageExtension(["digitalSignature", "contentCommitment"]),
141
+ extendedKeyUsageDocumentSigningExtension()
142
+ ];
143
+ }
144
+ export async function issueDocumentSigningCert(options) {
145
+ const keyPair = await generateKeyPair();
146
+ const built = await buildLeafCertificate(options.ca, keyPair.publicKey, {
147
+ subject: options.subject,
148
+ days: options.days,
149
+ notBefore: options.notBefore,
150
+ serialNumber: options.serialNumber
151
+ }, documentSigningProfileExtensions());
152
+ return {
153
+ certPem: built.certPem,
154
+ certDer: built.certDer,
155
+ privateKey: keyPair.privateKey,
156
+ publicKey: keyPair.publicKey,
157
+ certChainPem: built.certChainPem
158
+ };
159
+ }
136
160
  export async function importCertificateAuthority(options) {
137
161
  const issuerChainPem = options.issuerChainPem ?? "";
138
162
  assertIssuerChainPem(issuerChainPem);
package/dist/der.d.ts CHANGED
@@ -31,6 +31,7 @@ export declare function boolean(value: boolean): Uint8Array;
31
31
  export declare function integer(value: bigint | number | Uint8Array): Uint8Array;
32
32
  export declare function bitString(bytes: Uint8Array, unusedBits?: number): Uint8Array;
33
33
  export declare function octetString(bytes: Uint8Array): Uint8Array;
34
+ export declare function nullValue(): Uint8Array;
34
35
  export declare function utf8String(value: string): Uint8Array;
35
36
  export declare function printableString(value: string): Uint8Array;
36
37
  export declare function ia5String(value: string): Uint8Array;
package/dist/der.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"der.d.ts","sourceRoot":"","sources":["../src/der.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,GAAG;;;;;;;;;;;;;;CAcN,CAAC;AAEX,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,GAAG,EAAE,UAAU,CAAC;CACjB;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAE9D;AAED,wBAAgB,QAAQ,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,CAE9D;AAED,wBAAgB,GAAG,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,CAEzD;AAED,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAEzE;AAED,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAmB7C;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAElD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,CA4BvE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,SAAI,GAAG,UAAU,CAMvE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAEzD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAEpD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAMzD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAEnD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAEjF;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,CAO9C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,CAMtD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,SAAI,GAAG,UAAU,CAuBrE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE,CAMtE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,EAAE,CAW5D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CA4CnD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAevD"}
1
+ {"version":3,"file":"der.d.ts","sourceRoot":"","sources":["../src/der.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,GAAG;;;;;;;;;;;;;;CAcN,CAAC;AAEX,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,GAAG,EAAE,UAAU,CAAC;CACjB;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAE9D;AAED,wBAAgB,QAAQ,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,CAE9D;AAED,wBAAgB,GAAG,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,CAEzD;AAED,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAEzE;AAED,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAmB7C;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAElD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,CA4BvE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,SAAI,GAAG,UAAU,CAMvE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAEzD;AAED,wBAAgB,SAAS,IAAI,UAAU,CAEtC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAEpD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAMzD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAEnD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAEjF;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,CAO9C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,CAMtD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,SAAI,GAAG,UAAU,CAuBrE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE,CAMtE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,EAAE,CAW5D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CA4CnD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAevD"}
package/dist/der.js CHANGED
@@ -79,6 +79,9 @@ export function bitString(bytes, unusedBits = 0) {
79
79
  export function octetString(bytes) {
80
80
  return der(TAG.OCTET_STRING, bytes);
81
81
  }
82
+ export function nullValue() {
83
+ return new Uint8Array([TAG.NULL, 0x00]);
84
+ }
82
85
  export function utf8String(value) {
83
86
  return der(TAG.UTF8_STRING, utf8Bytes(value));
84
87
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export { createRootCA, importCertificateAuthority, issueClientCert, issueClientCertForPublicKey, issueIntermediateCA } from "./ca.js";
1
+ export { createRootCA, importCertificateAuthority, issueClientCert, issueClientCertForPublicKey, issueDocumentSigningCert, issueIntermediateCA } from "./ca.js";
2
2
  export { parseCertificateSigningRequest, verifyCertificateSigningRequestSignature, type ParsedCertificateSigningRequest, type CertificateSigningRequestExtension, type CertificateSigningRequestAttribute } from "./csr.js";
3
3
  export { pemToDer, certificateToPem } from "./pem.js";
4
+ export { exportPkcs12, type ExportPkcs12Input } from "./pkcs12.js";
4
5
  export { verifyClientCertificateIssuedBy, type VerifyClientCertificateIssuedByOptions, type VerifyClientCertificateValidity } from "./verify.js";
5
- export type { CertificateAuthority, CreateRootCAOptions, ImportCertificateAuthorityOptions, IssueClientCertForPublicKeyOptions, IssueClientCertOptions, IssueIntermediateCAOptions, IssuedClientCertificate, IssuedClientCertificateForPublicKey, SerialNumber, ShortSubjectAttributeType, Subject, SubjectAttribute, SubjectAttributeType } from "./types.js";
6
+ export type { CertificateAuthority, CreateRootCAOptions, ImportCertificateAuthorityOptions, IssueClientCertForPublicKeyOptions, IssueClientCertOptions, IssueDocumentSigningCertOptions, IssueIntermediateCAOptions, IssuedClientCertificate, IssuedClientCertificateForPublicKey, IssuedDocumentSigningCertificate, SerialNumber, ShortSubjectAttributeType, Subject, SubjectAttribute, SubjectAttributeType } from "./types.js";
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAC1B,eAAe,EACf,2BAA2B,EAC3B,mBAAmB,EACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,8BAA8B,EAC9B,wCAAwC,EACxC,KAAK,+BAA+B,EACpC,KAAK,kCAAkC,EACvC,KAAK,kCAAkC,EACxC,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EACL,+BAA+B,EAC/B,KAAK,sCAAsC,EAC3C,KAAK,+BAA+B,EACrC,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,iCAAiC,EACjC,kCAAkC,EAClC,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACvB,mCAAmC,EACnC,YAAY,EACZ,yBAAyB,EACzB,OAAO,EACP,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAC1B,eAAe,EACf,2BAA2B,EAC3B,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,8BAA8B,EAC9B,wCAAwC,EACxC,KAAK,+BAA+B,EACpC,KAAK,kCAAkC,EACvC,KAAK,kCAAkC,EACxC,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EACL,+BAA+B,EAC/B,KAAK,sCAAsC,EAC3C,KAAK,+BAA+B,EACrC,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,iCAAiC,EACjC,kCAAkC,EAClC,sBAAsB,EACtB,+BAA+B,EAC/B,0BAA0B,EAC1B,uBAAuB,EACvB,mCAAmC,EACnC,gCAAgC,EAChC,YAAY,EACZ,yBAAyB,EACzB,OAAO,EACP,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- export { createRootCA, importCertificateAuthority, issueClientCert, issueClientCertForPublicKey, issueIntermediateCA } from "./ca.js";
1
+ export { createRootCA, importCertificateAuthority, issueClientCert, issueClientCertForPublicKey, issueDocumentSigningCert, issueIntermediateCA } from "./ca.js";
2
2
  export { parseCertificateSigningRequest, verifyCertificateSigningRequestSignature } from "./csr.js";
3
3
  export { pemToDer, certificateToPem } from "./pem.js";
4
+ export { exportPkcs12 } from "./pkcs12.js";
4
5
  export { verifyClientCertificateIssuedBy } from "./verify.js";
package/dist/oids.d.ts CHANGED
@@ -14,7 +14,20 @@ export declare const OID: {
14
14
  readonly subjectKeyIdentifier: "2.5.29.14";
15
15
  readonly authorityKeyIdentifier: "2.5.29.35";
16
16
  readonly clientAuth: "1.3.6.1.5.5.7.3.2";
17
+ readonly documentSigning: "1.3.6.1.5.5.7.3.36";
17
18
  readonly extensionRequest: "1.2.840.113549.1.9.14";
19
+ readonly data: "1.2.840.113549.1.7.1";
20
+ readonly encryptedData: "1.2.840.113549.1.7.6";
21
+ readonly friendlyName: "1.2.840.113549.1.9.20";
22
+ readonly localKeyId: "1.2.840.113549.1.9.21";
23
+ readonly x509Certificate: "1.2.840.113549.1.9.22.1";
24
+ readonly certBag: "1.2.840.113549.1.12.10.1.3";
25
+ readonly pkcs8ShroudedKeyBag: "1.2.840.113549.1.12.10.1.2";
26
+ readonly pbes2: "1.2.840.113549.1.5.13";
27
+ readonly pbkdf2: "1.2.840.113549.1.5.12";
28
+ readonly hmacWithSha256: "1.2.840.113549.2.9";
29
+ readonly aes256Cbc: "2.16.840.1.101.3.4.1.42";
30
+ readonly sha256: "2.16.840.1.101.3.4.2.1";
18
31
  };
19
32
  export declare const SUBJECT_ATTRIBUTE_OIDS: Record<ShortSubjectAttributeType, string>;
20
33
  export declare const SUBJECT_VALUE_LENGTH_LIMITS: Record<ShortSubjectAttributeType, number>;
@@ -1 +1 @@
1
- {"version":3,"file":"oids.d.ts","sourceRoot":"","sources":["../src/oids.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE5D,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;CAgBN,CAAC;AAEX,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,yBAAyB,EAAE,MAAM,CAgB5E,CAAC;AAGF,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,yBAAyB,EAAE,MAAM,CAgBjF,CAAC;AAIF,eAAO,MAAM,wBAAwB,MAAM,CAAC"}
1
+ {"version":3,"file":"oids.d.ts","sourceRoot":"","sources":["../src/oids.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE5D,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BN,CAAC;AAEX,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,yBAAyB,EAAE,MAAM,CAgB5E,CAAC;AAGF,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,yBAAyB,EAAE,MAAM,CAgBjF,CAAC;AAIF,eAAO,MAAM,wBAAwB,MAAM,CAAC"}
package/dist/oids.js CHANGED
@@ -13,7 +13,20 @@ export const OID = {
13
13
  subjectKeyIdentifier: "2.5.29.14",
14
14
  authorityKeyIdentifier: "2.5.29.35",
15
15
  clientAuth: "1.3.6.1.5.5.7.3.2",
16
- extensionRequest: "1.2.840.113549.1.9.14"
16
+ documentSigning: "1.3.6.1.5.5.7.3.36",
17
+ extensionRequest: "1.2.840.113549.1.9.14",
18
+ data: "1.2.840.113549.1.7.1",
19
+ encryptedData: "1.2.840.113549.1.7.6",
20
+ friendlyName: "1.2.840.113549.1.9.20",
21
+ localKeyId: "1.2.840.113549.1.9.21",
22
+ x509Certificate: "1.2.840.113549.1.9.22.1",
23
+ certBag: "1.2.840.113549.1.12.10.1.3",
24
+ pkcs8ShroudedKeyBag: "1.2.840.113549.1.12.10.1.2",
25
+ pbes2: "1.2.840.113549.1.5.13",
26
+ pbkdf2: "1.2.840.113549.1.5.12",
27
+ hmacWithSha256: "1.2.840.113549.2.9",
28
+ aes256Cbc: "2.16.840.1.101.3.4.1.42",
29
+ sha256: "2.16.840.1.101.3.4.2.1"
17
30
  };
18
31
  export const SUBJECT_ATTRIBUTE_OIDS = {
19
32
  CN: "2.5.4.3",
@@ -0,0 +1,11 @@
1
+ export interface ExportPkcs12Input {
2
+ certDer: Uint8Array;
3
+ chainDer?: Uint8Array[];
4
+ privateKey: CryptoKey;
5
+ password: Uint8Array;
6
+ friendlyName?: Uint8Array;
7
+ iterations?: number;
8
+ macIterations?: number;
9
+ }
10
+ export declare function exportPkcs12(input: ExportPkcs12Input): Promise<Uint8Array>;
11
+ //# sourceMappingURL=pkcs12.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkcs12.d.ts","sourceRoot":"","sources":["../src/pkcs12.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,UAAU,EAAE,SAAS,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;IACrB,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAUD,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CA8FhF"}
package/dist/pkcs12.js ADDED
@@ -0,0 +1,248 @@
1
+ import { arrayBufferFromBytes, concatBytes, randomBytes } from "./bytes.js";
2
+ import { digestSha256, keyIdentifierFromSpki } from "./crypto.js";
3
+ import { contextPrimitive, der, explicit, integer, nullValue, octetString, oid, sequence, set } from "./der.js";
4
+ import { OID } from "./oids.js";
5
+ import { parseCertificateDer } from "./parser.js";
6
+ const DEFAULT_PBKDF2_ITERATIONS = 600_000;
7
+ const DEFAULT_MAC_ITERATIONS = 100_000;
8
+ const SALT_LENGTH = 16;
9
+ const IV_LENGTH = 16;
10
+ const MAC_KEY_LENGTH = 32;
11
+ const SHA256_BLOCK_SIZE = 64;
12
+ const PKCS12_KDF_ID_MAC = 3;
13
+ export async function exportPkcs12(input) {
14
+ const iterations = input.iterations ?? DEFAULT_PBKDF2_ITERATIONS;
15
+ const macIterations = input.macIterations ?? DEFAULT_MAC_ITERATIONS;
16
+ validateInput(input, iterations, macIterations);
17
+ const parsedLeaf = await parseCertificateDer(input.certDer);
18
+ const localKeyId = await keyIdentifierFromSpki(parsedLeaf.subjectPublicKeyInfoDer);
19
+ const friendlyNameAttr = input.friendlyName !== undefined && input.friendlyName.length > 0
20
+ ? buildFriendlyNameAttr(input.friendlyName)
21
+ : undefined;
22
+ const localKeyIdAttr = buildLocalKeyIdAttr(localKeyId);
23
+ const leafAttrs = friendlyNameAttr ? [localKeyIdAttr, friendlyNameAttr] : [localKeyIdAttr];
24
+ const certBags = [buildCertSafeBag(input.certDer, leafAttrs)];
25
+ if (input.chainDer) {
26
+ for (const c of input.chainDer) {
27
+ certBags.push(buildCertSafeBag(c, []));
28
+ }
29
+ }
30
+ const certSafeContents = sequence(...certBags);
31
+ // Import the password into a non-extractable PBKDF2 baseKey once and reuse
32
+ // it across both cert-bag and key-bag encryption. This halves the number of
33
+ // password-byte ArrayBuffer copies handed to WebCrypto (which we cannot
34
+ // wipe) from two to one.
35
+ const pbkdf2BaseKey = await crypto.subtle.importKey("raw", arrayBufferFromBytes(input.password), "PBKDF2", false, ["deriveKey"]);
36
+ const certEncrypted = await pbes2EncryptAesCbc(certSafeContents, pbkdf2BaseKey, iterations);
37
+ const certContentInfo = sequence(oid(OID.encryptedData), explicit(0, sequence(integer(0n), sequence(oid(OID.data), certEncrypted.algorithm, contextPrimitive(0, certEncrypted.ciphertext)))));
38
+ const pkcs8 = new Uint8Array(await crypto.subtle.exportKey("pkcs8", input.privateKey));
39
+ const keyEncrypted = await pbes2EncryptAesCbc(pkcs8, pbkdf2BaseKey, iterations);
40
+ wipe(pkcs8);
41
+ const epki = sequence(keyEncrypted.algorithm, octetString(keyEncrypted.ciphertext));
42
+ const keyBag = buildKeySafeBag(epki, leafAttrs);
43
+ const keySafeContents = sequence(keyBag);
44
+ const keyContentInfo = sequence(oid(OID.data), explicit(0, octetString(keySafeContents)));
45
+ const authenticatedSafe = sequence(certContentInfo, keyContentInfo);
46
+ const macSalt = randomBytes(SALT_LENGTH);
47
+ const passwordUtf16 = utf8ToUtf16BeWithTerminator(input.password);
48
+ const macKey = await pkcs12V1KdfMacKey(passwordUtf16, macSalt, macIterations);
49
+ wipe(passwordUtf16);
50
+ const macKeyHandle = await crypto.subtle.importKey("raw", arrayBufferFromBytes(macKey), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
51
+ wipe(macKey);
52
+ const mac = new Uint8Array(await crypto.subtle.sign("HMAC", macKeyHandle, arrayBufferFromBytes(authenticatedSafe)));
53
+ const macData = sequence(sequence(sequence(oid(OID.sha256), nullValue()), octetString(mac)), octetString(macSalt), integer(BigInt(macIterations)));
54
+ const pfxAuthSafeContentInfo = sequence(oid(OID.data), explicit(0, octetString(authenticatedSafe)));
55
+ return sequence(integer(3n), pfxAuthSafeContentInfo, macData);
56
+ }
57
+ function validateInput(input, iterations, macIterations) {
58
+ if (!(input.password instanceof Uint8Array) || input.password.length === 0) {
59
+ throw new Error("password must be a non-empty Uint8Array of UTF-8 bytes");
60
+ }
61
+ if (!input.privateKey.extractable) {
62
+ throw new Error("privateKey must be extractable");
63
+ }
64
+ if (input.privateKey.algorithm.name !== "ECDSA") {
65
+ throw new Error("privateKey must be an ECDSA key");
66
+ }
67
+ if (!Number.isInteger(iterations) || iterations < 1) {
68
+ throw new Error("iterations must be a positive integer");
69
+ }
70
+ if (!Number.isInteger(macIterations) || macIterations < 1) {
71
+ throw new Error("macIterations must be a positive integer");
72
+ }
73
+ if (input.friendlyName !== undefined && !(input.friendlyName instanceof Uint8Array)) {
74
+ throw new Error("friendlyName must be a Uint8Array of UTF-8 bytes");
75
+ }
76
+ }
77
+ function buildCertSafeBag(certDer, attrs) {
78
+ const certBagInner = sequence(oid(OID.x509Certificate), explicit(0, octetString(certDer)));
79
+ return safeBag(OID.certBag, certBagInner, attrs);
80
+ }
81
+ function buildKeySafeBag(encryptedPrivateKeyInfo, attrs) {
82
+ return safeBag(OID.pkcs8ShroudedKeyBag, encryptedPrivateKeyInfo, attrs);
83
+ }
84
+ function safeBag(bagOid, bagValue, attrs) {
85
+ const parts = [oid(bagOid), explicit(0, bagValue)];
86
+ if (attrs.length > 0) {
87
+ parts.push(canonicalSetOf(attrs));
88
+ }
89
+ return sequence(...parts);
90
+ }
91
+ // X.690 §11.6: SET OF components are encoded in ascending order of their
92
+ // encoded octet strings, with the shorter component padded with trailing
93
+ // 0-octets for the comparison. Used for bagAttributes.
94
+ function canonicalSetOf(children) {
95
+ const sorted = [...children].sort(derSetCompare);
96
+ return set(...sorted);
97
+ }
98
+ function derSetCompare(a, b) {
99
+ const len = Math.max(a.length, b.length);
100
+ for (let i = 0; i < len; i += 1) {
101
+ const av = i < a.length ? a[i] : 0;
102
+ const bv = i < b.length ? b[i] : 0;
103
+ if (av !== bv)
104
+ return av - bv;
105
+ }
106
+ return 0;
107
+ }
108
+ function buildLocalKeyIdAttr(localKeyId) {
109
+ return sequence(oid(OID.localKeyId), set(octetString(localKeyId)));
110
+ }
111
+ function buildFriendlyNameAttr(friendlyNameUtf8) {
112
+ return sequence(oid(OID.friendlyName), set(bmpString(friendlyNameUtf8)));
113
+ }
114
+ function bmpString(utf8) {
115
+ const utf16 = utf8ToUtf16Be(utf8);
116
+ return der(0x1e, utf16);
117
+ }
118
+ async function pbes2EncryptAesCbc(plaintext, pbkdf2BaseKey, iterations) {
119
+ const salt = randomBytes(SALT_LENGTH);
120
+ const iv = randomBytes(IV_LENGTH);
121
+ const aesKey = await crypto.subtle.deriveKey({ name: "PBKDF2", salt: arrayBufferFromBytes(salt), iterations, hash: "SHA-256" }, pbkdf2BaseKey, { name: "AES-CBC", length: 256 }, false, ["encrypt"]);
122
+ const ciphertext = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-CBC", iv: arrayBufferFromBytes(iv) }, aesKey, arrayBufferFromBytes(plaintext)));
123
+ return {
124
+ algorithm: algorithmIdentifierPbes2(salt, iterations, iv),
125
+ ciphertext
126
+ };
127
+ }
128
+ function algorithmIdentifierPbes2(salt, iterations, iv) {
129
+ const pbkdf2Params = sequence(octetString(salt), integer(BigInt(iterations)), sequence(oid(OID.hmacWithSha256), nullValue()));
130
+ const keyDerivationFunc = sequence(oid(OID.pbkdf2), pbkdf2Params);
131
+ const encryptionScheme = sequence(oid(OID.aes256Cbc), octetString(iv));
132
+ return sequence(oid(OID.pbes2), sequence(keyDerivationFunc, encryptionScheme));
133
+ }
134
+ // PKCS#12 v1 KDF (RFC 7292 App.B) producing an HMAC-SHA-256 key (32 bytes).
135
+ // Specialized for ID=3, n=u=32, v=64. Single-block output: no I update needed.
136
+ async function pkcs12V1KdfMacKey(passwordUtf16, salt, iterations) {
137
+ const v = SHA256_BLOCK_SIZE;
138
+ const D = new Uint8Array(v).fill(PKCS12_KDF_ID_MAC);
139
+ const sLen = Math.ceil(salt.length / v) * v;
140
+ const S2 = new Uint8Array(sLen);
141
+ for (let i = 0; i < sLen; i += 1) {
142
+ S2[i] = salt[i % salt.length];
143
+ }
144
+ const pLen = Math.ceil(passwordUtf16.length / v) * v;
145
+ const P2 = new Uint8Array(pLen);
146
+ for (let i = 0; i < pLen; i += 1) {
147
+ P2[i] = passwordUtf16[i % passwordUtf16.length];
148
+ }
149
+ const I = concatBytes([S2, P2]);
150
+ // T_0 holds D || S2 || P2 (raw password bytes embedded in P2).
151
+ // Each digestSha256 returns a fresh 32-byte buffer; the previous T's buffer
152
+ // becomes unreachable but, without an explicit wipe, would sit on the JS
153
+ // heap until GC. Zero it before reassigning. Successive Ts are H^j(D||I)
154
+ // values, which let an attacker reach H^c(D||I) = MAC key by continuing the
155
+ // chain — they're as sensitive as the MAC key itself.
156
+ let T = concatBytes([D, I]);
157
+ for (let j = 0; j < iterations; j += 1) {
158
+ const next = await digestSha256(T);
159
+ T.fill(0);
160
+ T = next;
161
+ }
162
+ wipe(D, S2, P2, I);
163
+ return T.subarray(0, MAC_KEY_LENGTH);
164
+ }
165
+ // Convert UTF-8 bytes to UTF-16BE bytes plus a 0x00 0x00 terminator,
166
+ // without going through any JavaScript string. Walks code points by hand.
167
+ function utf8ToUtf16BeWithTerminator(utf8) {
168
+ const utf16 = utf8ToUtf16Be(utf8);
169
+ const out = new Uint8Array(utf16.length + 2);
170
+ out.set(utf16, 0);
171
+ wipe(utf16);
172
+ return out;
173
+ }
174
+ // Two-pass to avoid an intermediate `number[]` that would retain
175
+ // password-derived bytes on the JS heap until GC. Pass 1 sizes the output;
176
+ // pass 2 writes directly into a tight Uint8Array. Both passes share the same
177
+ // boundary checks so an invalid leader byte fails fast in pass 1.
178
+ function utf8ToUtf16Be(utf8) {
179
+ let outLen = 0;
180
+ let i = 0;
181
+ while (i < utf8.length) {
182
+ const b1 = utf8[i];
183
+ if (b1 < 0x80) {
184
+ outLen += 2;
185
+ i += 1;
186
+ }
187
+ else if ((b1 & 0xe0) === 0xc0 && i + 1 < utf8.length) {
188
+ outLen += 2;
189
+ i += 2;
190
+ }
191
+ else if ((b1 & 0xf0) === 0xe0 && i + 2 < utf8.length) {
192
+ outLen += 2;
193
+ i += 3;
194
+ }
195
+ else if ((b1 & 0xf8) === 0xf0 && i + 3 < utf8.length) {
196
+ outLen += 4;
197
+ i += 4;
198
+ }
199
+ else {
200
+ throw new Error("Invalid UTF-8 sequence");
201
+ }
202
+ }
203
+ const out = new Uint8Array(outLen);
204
+ let oi = 0;
205
+ i = 0;
206
+ while (i < utf8.length) {
207
+ const b1 = utf8[i];
208
+ let cp;
209
+ if (b1 < 0x80) {
210
+ cp = b1;
211
+ i += 1;
212
+ }
213
+ else if ((b1 & 0xe0) === 0xc0) {
214
+ cp = ((b1 & 0x1f) << 6) | (utf8[i + 1] & 0x3f);
215
+ i += 2;
216
+ }
217
+ else if ((b1 & 0xf0) === 0xe0) {
218
+ cp = ((b1 & 0x0f) << 12) | ((utf8[i + 1] & 0x3f) << 6) | (utf8[i + 2] & 0x3f);
219
+ i += 3;
220
+ }
221
+ else {
222
+ cp = ((b1 & 0x07) << 18)
223
+ | ((utf8[i + 1] & 0x3f) << 12)
224
+ | ((utf8[i + 2] & 0x3f) << 6)
225
+ | (utf8[i + 3] & 0x3f);
226
+ i += 4;
227
+ }
228
+ if (cp < 0x10000) {
229
+ out[oi++] = (cp >> 8) & 0xff;
230
+ out[oi++] = cp & 0xff;
231
+ }
232
+ else {
233
+ const adj = cp - 0x10000;
234
+ const high = 0xd800 + ((adj >> 10) & 0x3ff);
235
+ const low = 0xdc00 + (adj & 0x3ff);
236
+ out[oi++] = (high >> 8) & 0xff;
237
+ out[oi++] = high & 0xff;
238
+ out[oi++] = (low >> 8) & 0xff;
239
+ out[oi++] = low & 0xff;
240
+ }
241
+ }
242
+ return out;
243
+ }
244
+ function wipe(...bufs) {
245
+ for (const b of bufs) {
246
+ b.fill(0);
247
+ }
248
+ }
package/dist/types.d.ts CHANGED
@@ -62,6 +62,20 @@ export interface IssuedClientCertificateForPublicKey {
62
62
  certDer: Uint8Array;
63
63
  certChainPem: string;
64
64
  }
65
+ export interface IssueDocumentSigningCertOptions {
66
+ ca: CertificateAuthority;
67
+ subject: Subject;
68
+ days: number;
69
+ notBefore?: Date;
70
+ serialNumber?: SerialNumber;
71
+ }
72
+ export interface IssuedDocumentSigningCertificate {
73
+ certPem: string;
74
+ certDer: Uint8Array;
75
+ privateKey: CryptoKey;
76
+ publicKey: CryptoKey;
77
+ certChainPem: string;
78
+ }
65
79
  export interface ImportCertificateAuthorityOptions {
66
80
  certPem: string;
67
81
  privateKey: CryptoKey;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,yBAAyB,GACjC,IAAI,GACJ,GAAG,GACH,IAAI,GACJ,GAAG,GACH,IAAI,GACJ,GAAG,GACH,GAAG,GACH,IAAI,GACJ,cAAc,GACd,QAAQ,GACR,YAAY,GACZ,OAAO,GACP,WAAW,GACX,SAAS,GACT,KAAK,CAAC;AAEV,MAAM,MAAM,SAAS,GAAG,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,EAAE,CAAC;AAEvD,MAAM,MAAM,oBAAoB,GAAG,yBAAyB,GAAG,SAAS,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;AAEzC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC;IACpB,UAAU,EAAE,SAAS,CAAC;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC;IACpB,UAAU,EAAE,SAAS,CAAC;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,oBAAoB,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,oBAAoB,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,kCAAkC;IACjD,EAAE,EAAE,oBAAoB,CAAC;IACzB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,mCAAmC;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iCAAiC;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,SAAS,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/x509.d.ts CHANGED
@@ -23,11 +23,13 @@ export declare function basicConstraintsCaExtension(pathLenConstraint: number):
23
23
  export declare function basicConstraintsLeafExtension(): Uint8Array;
24
24
  export declare function keyUsageExtension(usages: readonly KeyUsageBit[]): Uint8Array;
25
25
  export declare function extendedKeyUsageClientAuthExtension(): Uint8Array;
26
+ export declare function extendedKeyUsageDocumentSigningExtension(): Uint8Array;
26
27
  export declare function subjectKeyIdentifierExtension(keyIdentifier: Uint8Array): Uint8Array;
27
28
  export declare function authorityKeyIdentifierExtension(keyIdentifier: Uint8Array): Uint8Array;
28
29
  export declare function subjectAltNameExtension(dnsNames?: readonly string[], ipAddresses?: readonly string[]): Uint8Array | undefined;
29
30
  declare const KEY_USAGE_BITS: {
30
31
  readonly digitalSignature: 0;
32
+ readonly contentCommitment: 1;
31
33
  readonly keyCertSign: 5;
32
34
  readonly cRLSign: 6;
33
35
  };
@@ -1 +1 @@
1
- {"version":3,"file":"x509.d.ts","sourceRoot":"","sources":["../src/x509.ts"],"names":[],"mappings":"AACA,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAkBjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACxC,SAAS,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,UAAU,CAAC;IAC1B,cAAc,EAAE,UAAU,CAAC;IAC3B,uBAAuB,EAAE,UAAU,CAAC;IACpC,UAAU,EAAE,UAAU,EAAE,CAAC;IACzB,WAAW,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,iBAAiB,EAAE,UAAU,CAAC;IAC9B,eAAe,EAAE,UAAU,CAAC;IAC5B,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,IAAI,CAAC;CAChB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,GAAG,oBAAoB,CAoBtF;AAED,wBAAgB,gBAAgB,CAC9B,iBAAiB,EAAE,UAAU,EAC7B,YAAY,EAAE,UAAU,EACxB,WAAW,EAAE,cAAc,GAC1B,UAAU,CAEZ;AAED,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,cAAc,GAAG,UAAU,CAEnF;AAED,wBAAgB,2BAA2B,CAAC,iBAAiB,EAAE,MAAM,GAAG,UAAU,CAMjF;AAED,wBAAgB,6BAA6B,IAAI,UAAU,CAE1D;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,UAAU,CAgB5E;AAED,wBAAgB,mCAAmC,IAAI,UAAU,CAEhE;AAED,wBAAgB,6BAA6B,CAAC,aAAa,EAAE,UAAU,GAAG,UAAU,CAEnF;AAED,wBAAgB,+BAA+B,CAAC,aAAa,EAAE,UAAU,GAAG,UAAU,CAErF;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,GAAG,SAAS,CAmC7H;AAwID,QAAA,MAAM,cAAc;;;;CAIV,CAAC;AAEX,KAAK,WAAW,GAAG,MAAM,OAAO,cAAc,CAAC"}
1
+ {"version":3,"file":"x509.d.ts","sourceRoot":"","sources":["../src/x509.ts"],"names":[],"mappings":"AACA,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAkBjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACxC,SAAS,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,UAAU,CAAC;IAC1B,cAAc,EAAE,UAAU,CAAC;IAC3B,uBAAuB,EAAE,UAAU,CAAC;IACpC,UAAU,EAAE,UAAU,EAAE,CAAC;IACzB,WAAW,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,iBAAiB,EAAE,UAAU,CAAC;IAC9B,eAAe,EAAE,UAAU,CAAC;IAC5B,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,IAAI,CAAC;CAChB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,GAAG,oBAAoB,CAoBtF;AAED,wBAAgB,gBAAgB,CAC9B,iBAAiB,EAAE,UAAU,EAC7B,YAAY,EAAE,UAAU,EACxB,WAAW,EAAE,cAAc,GAC1B,UAAU,CAEZ;AAED,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,cAAc,GAAG,UAAU,CAEnF;AAED,wBAAgB,2BAA2B,CAAC,iBAAiB,EAAE,MAAM,GAAG,UAAU,CAMjF;AAED,wBAAgB,6BAA6B,IAAI,UAAU,CAE1D;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,UAAU,CAgB5E;AAED,wBAAgB,mCAAmC,IAAI,UAAU,CAEhE;AAED,wBAAgB,wCAAwC,IAAI,UAAU,CAErE;AAED,wBAAgB,6BAA6B,CAAC,aAAa,EAAE,UAAU,GAAG,UAAU,CAEnF;AAED,wBAAgB,+BAA+B,CAAC,aAAa,EAAE,UAAU,GAAG,UAAU,CAErF;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,GAAG,SAAS,CAmC7H;AAuID,QAAA,MAAM,cAAc;;;;;CAKV,CAAC;AAEX,KAAK,WAAW,GAAG,MAAM,OAAO,cAAc,CAAC"}
package/dist/x509.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asciiBytes, concatBytes } from "./bytes.js";
1
+ import { asciiBytes, concatBytes, randomBytes } from "./bytes.js";
2
2
  import { signatureAlgorithmOidForCurve } from "./crypto.js";
3
3
  import { bitString, boolean, contextPrimitive, der, explicit, generalizedTime, integer, octetString, oid, readElement, sequence, TAG, utcTime } from "./der.js";
4
4
  import { encodeIpAddress } from "./ip.js";
@@ -43,6 +43,9 @@ export function keyUsageExtension(usages) {
43
43
  export function extendedKeyUsageClientAuthExtension() {
44
44
  return extension(OID.extendedKeyUsage, false, sequence(oid(OID.clientAuth)));
45
45
  }
46
+ export function extendedKeyUsageDocumentSigningExtension() {
47
+ return extension(OID.extendedKeyUsage, false, sequence(oid(OID.documentSigning)));
48
+ }
46
49
  export function subjectKeyIdentifierExtension(keyIdentifier) {
47
50
  return extension(OID.subjectKeyIdentifier, false, octetString(keyIdentifier));
48
51
  }
@@ -106,8 +109,7 @@ function encodeSerialNumber(serialNumber) {
106
109
  }
107
110
  function encodeSerialNumberDer(serialNumber) {
108
111
  if (serialNumber === undefined) {
109
- const bytes = new Uint8Array(16);
110
- crypto.getRandomValues(bytes);
112
+ const bytes = randomBytes(16);
111
113
  bytes[0] = bytes[0] & 0x7f;
112
114
  if (bytes.every((byte) => byte === 0)) {
113
115
  bytes[15] = 1;
@@ -193,6 +195,7 @@ function assertYearInRange(year, fieldName) {
193
195
  }
194
196
  const KEY_USAGE_BITS = {
195
197
  digitalSignature: 0,
198
+ contentCommitment: 1,
196
199
  keyCertSign: 5,
197
200
  cRLSign: 6
198
201
  };