@joclaim/tls 0.1.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.
Files changed (80) hide show
  1. package/README.md +221 -0
  2. package/lib/crypto/common.d.ts +3 -0
  3. package/lib/crypto/common.js +26 -0
  4. package/lib/crypto/index.d.ts +3 -0
  5. package/lib/crypto/index.js +4 -0
  6. package/lib/crypto/insecure-rand.d.ts +1 -0
  7. package/lib/crypto/insecure-rand.js +9 -0
  8. package/lib/crypto/pure-js.d.ts +2 -0
  9. package/lib/crypto/pure-js.js +144 -0
  10. package/lib/crypto/webcrypto.d.ts +3 -0
  11. package/lib/crypto/webcrypto.js +310 -0
  12. package/lib/index.d.ts +4 -0
  13. package/lib/index.js +4 -0
  14. package/lib/make-tls-client.d.ts +74 -0
  15. package/lib/make-tls-client.js +657 -0
  16. package/lib/scripts/build-jsc.d.ts +1 -0
  17. package/lib/scripts/build-jsc.js +20 -0
  18. package/lib/scripts/ca-template.d.ts +5 -0
  19. package/lib/scripts/ca-template.js +6 -0
  20. package/lib/scripts/fallbacks/crypto.d.ts +4 -0
  21. package/lib/scripts/fallbacks/crypto.js +2 -0
  22. package/lib/scripts/handshake.d.ts +1 -0
  23. package/lib/scripts/handshake.js +61 -0
  24. package/lib/scripts/jsc.d.ts +28 -0
  25. package/lib/scripts/jsc.js +92 -0
  26. package/lib/scripts/update-ca-certs.d.ts +1 -0
  27. package/lib/scripts/update-ca-certs.js +29 -0
  28. package/lib/types/crypto.d.ts +62 -0
  29. package/lib/types/crypto.js +1 -0
  30. package/lib/types/index.d.ts +15 -0
  31. package/lib/types/index.js +4 -0
  32. package/lib/types/logger.d.ts +6 -0
  33. package/lib/types/logger.js +1 -0
  34. package/lib/types/tls.d.ts +141 -0
  35. package/lib/types/tls.js +1 -0
  36. package/lib/types/x509.d.ts +32 -0
  37. package/lib/types/x509.js +1 -0
  38. package/lib/utils/additional-root-cas.d.ts +1 -0
  39. package/lib/utils/additional-root-cas.js +197 -0
  40. package/lib/utils/client-hello.d.ts +23 -0
  41. package/lib/utils/client-hello.js +167 -0
  42. package/lib/utils/constants.d.ts +239 -0
  43. package/lib/utils/constants.js +244 -0
  44. package/lib/utils/decryption-utils.d.ts +64 -0
  45. package/lib/utils/decryption-utils.js +166 -0
  46. package/lib/utils/finish-messages.d.ts +11 -0
  47. package/lib/utils/finish-messages.js +49 -0
  48. package/lib/utils/generics.d.ts +35 -0
  49. package/lib/utils/generics.js +146 -0
  50. package/lib/utils/index.d.ts +18 -0
  51. package/lib/utils/index.js +18 -0
  52. package/lib/utils/key-share.d.ts +13 -0
  53. package/lib/utils/key-share.js +72 -0
  54. package/lib/utils/key-update.d.ts +2 -0
  55. package/lib/utils/key-update.js +14 -0
  56. package/lib/utils/logger.d.ts +2 -0
  57. package/lib/utils/logger.js +15 -0
  58. package/lib/utils/make-queue.d.ts +3 -0
  59. package/lib/utils/make-queue.js +22 -0
  60. package/lib/utils/mozilla-root-cas.d.ts +5 -0
  61. package/lib/utils/mozilla-root-cas.js +4459 -0
  62. package/lib/utils/packets.d.ts +51 -0
  63. package/lib/utils/packets.js +148 -0
  64. package/lib/utils/parse-alert.d.ts +7 -0
  65. package/lib/utils/parse-alert.js +28 -0
  66. package/lib/utils/parse-certificate.d.ts +29 -0
  67. package/lib/utils/parse-certificate.js +188 -0
  68. package/lib/utils/parse-client-hello.d.ts +11 -0
  69. package/lib/utils/parse-client-hello.js +39 -0
  70. package/lib/utils/parse-extensions.d.ts +11 -0
  71. package/lib/utils/parse-extensions.js +74 -0
  72. package/lib/utils/parse-server-hello.d.ts +10 -0
  73. package/lib/utils/parse-server-hello.js +52 -0
  74. package/lib/utils/session-ticket.d.ts +17 -0
  75. package/lib/utils/session-ticket.js +51 -0
  76. package/lib/utils/wrapped-record.d.ts +25 -0
  77. package/lib/utils/wrapped-record.js +191 -0
  78. package/lib/utils/x509.d.ts +5 -0
  79. package/lib/utils/x509.js +124 -0
  80. package/package.json +82 -0
package/README.md ADDED
@@ -0,0 +1,221 @@
1
+ <div>
2
+ <div>
3
+ <img src="https://raw.githubusercontent.com/reclaimprotocol/.github/main/assets/banners/TLS.png" />
4
+ </div>
5
+ </div>
6
+
7
+ A TLS client implementation in typescript. This library is fully compatible with the browser (without any polyfills), and on any other JavaScript environment.
8
+
9
+ As all the cryptography is handled by either "webcrypto" or a "pure-js" implementation if webcrypto is not available.
10
+
11
+ ## Dependencies
12
+
13
+ 1. The ChaCha20-Poly1305 cipher is not supported via WebCrypto -- so we utilise `@stablelib/chacha20-poly1305` to provide this functionality.
14
+ 2. To handle X509 certificate validation we utilise `@peculiar/x509`
15
+ 3. Optionally a few other crypto dependencies are used when using the `pure-js` implementation. These can be excluded when using WebCrypto.
16
+
17
+ ## Supported Crypto Suites & Versions
18
+
19
+ ### TLS
20
+ - TLS 1.2
21
+ - TLS 1.3
22
+
23
+ ### Curves
24
+ - X25519 (only on NodeJs -- not supported in the browser)
25
+ - P-256 (SECP256R1)
26
+ - P-384 (SECP384R1)
27
+
28
+ ### Signature Algorithms
29
+ - RSA-PSS-RSAE-SHA256
30
+ - ECDSA-SECP256R1-SHA256
31
+ - ECDSA-SECP256R1-SHA384
32
+ - ECDSA-SECP384R1-SHA256
33
+ - ECDSA-SECP384R1-SHA384
34
+ - RSA-PKCS1-SHA256
35
+ - RSA-PKCS1-SHA384
36
+ - RSA-PKCS1-SHA512
37
+ - RSA-PKCS1-SHA1
38
+
39
+ ### Cipher Suites (TLS 1.3)
40
+ - AES-128-GCM-SHA256
41
+ - AES-256-GCM-SHA384
42
+ - CHACHA20-POLY1305-SHA256
43
+
44
+ ### Cipher Suites (TLS 1.2)
45
+ - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
46
+ - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
47
+ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
48
+ - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
49
+ - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
50
+ - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
51
+ - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
52
+ - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
53
+
54
+ ### Certificates
55
+ - The entire Mozilla CA store is supported
56
+ - A few additional certificates have also been added. See `src/utils/root-ca.ts`
57
+ - We also implement fetching intermediate certificates via AIA fetching. Any fetched certificates are also then verified against the root CA store.
58
+
59
+ ## Install
60
+
61
+ Edge version:
62
+ ``` sh
63
+ npm i git+https://github.com/reclaimprotocol/tls
64
+ ```
65
+
66
+ ## Set Crypto Implementation
67
+
68
+ When on the browser, NodeJS or another NodeJS like runtime (such as Bun), you can set the crypto implementation to use the native `webcrypto` API. This is the most performant way to use this library.
69
+ ``` ts
70
+ import { setCryptoImplementation } from '@reclaimprotocol/tls'
71
+ import { webcryptoCrypto } from '@reclaimprotocol/tls/webcrypto'
72
+
73
+ setCryptoImplementation(webcryptoCrypto)
74
+ ```
75
+
76
+ If webcrypto is not available, you can use the `pure-js` implementation. This is slower, but works in all JavaScript environments -- even JavascriptCore.
77
+ ``` ts
78
+ import { setCryptoImplementation } from '@reclaimprotocol/tls'
79
+ import { pureJsCrypto } from '@reclaimprotocol/tls/pure-js'
80
+
81
+ setCryptoImplementation(pureJsCrypto)
82
+ ```
83
+
84
+ ## Example Usage
85
+
86
+ After you've set the crypto implementation, you can use the TLS client like this:
87
+
88
+ ``` ts
89
+ import { Socket } from 'net'
90
+ import { makeTLSClient, uint8ArrayToBinaryStr } from '@reclaimprotocol/tls'
91
+
92
+ const socket = new Socket()
93
+ const host = 'www.google.com'
94
+ const port = 443
95
+
96
+ const tls = makeTLSClient({
97
+ host,
98
+ // verify the server's certificate
99
+ // disable when using self-signed certificates
100
+ // or if you don't care about the authenticity
101
+ // of the server
102
+ verifyServerCertificate: true,
103
+ // only use the following cipher suites
104
+ // leave undefined to use all supported cipher suites
105
+ cipherSuites: [
106
+ 'TLS_CHACHA20_POLY1305_SHA256'
107
+ // ... other suites
108
+ ],
109
+ // write raw bytes to the socket
110
+ async write({ header, content }) {
111
+ socket.write(header)
112
+ socket.write(content)
113
+ },
114
+ onHandshake() {
115
+ console.log('handshake completed successfully')
116
+ // write encrypted data to the socket
117
+ const getReq = `GET / HTTP/1.1\r\nHost: ${host}\r\n\r\n`
118
+ tls.write(Buffer.from(getReq))
119
+ },
120
+ onApplicationData(plaintext) {
121
+ const str = uint8ArrayToBinaryStr(plaintext)
122
+ console.log('received application data: ', str)
123
+ },
124
+ onTlsEnd(error) {
125
+ console.error('TLS connect ended: ', error)
126
+ }
127
+ })
128
+
129
+ socket.on('data', tls.handleReceivedBytes)
130
+
131
+ // start handshake as soon as the socket connects
132
+ socket.on('connect', () => tls.startHandshake())
133
+
134
+ // use the TCP socket to connect to the server
135
+ socket.connect({ host, port })
136
+ ```
137
+
138
+ ### Misc API Usage
139
+
140
+ Handle a Session Ticket & Resume Session with a PSK
141
+ ``` ts
142
+ const tlsClient = makeTlsClient({
143
+ // ... other options
144
+ onSessionTicket(ticket) {
145
+ // get a PSK (pre-shared key) from the session ticket
146
+ const psk = tls.getPskFromTicket(ticket)
147
+ // this can be used to resume a session
148
+ // if disconnected, using
149
+ // tls.startHandshake({ psk })
150
+ }
151
+ })
152
+ ```
153
+
154
+ Handle received certificates
155
+ ``` ts
156
+ const tlsClient = makeTlsClient({
157
+ // ... other options
158
+
159
+ // handle received certificates
160
+ // (if you want to for some reason)
161
+ onRecvCertificates({ certificates }) {
162
+ // do something I guess?
163
+ }
164
+ })
165
+ ```
166
+
167
+ Use the TLS KeyUpdate method to update the traffic keys. This sends a KeyUpdate message to the server & generates a fresh set of keys to encrypt/decrypt data. The server will then respond with a KeyUpdate message of its own. This is useful for forward secrecy.
168
+ ```ts
169
+ await tls.updateTrafficKeys()
170
+ ```
171
+
172
+ ## Testing
173
+
174
+ Once you clone the repository, install dependencies via `npm i`, you can run the tests using:
175
+ ```bash
176
+ npm run test:webcrypto
177
+ ```
178
+ to test the WebCrypto implementation, or
179
+ ```bash
180
+ npm run test:pure-js
181
+ ```
182
+ to test the PureJS implementation.
183
+
184
+ If you want to test a connection to a host, you can use the `handshake.ts` script. This script will connect to the specified host and port, perform a TLS handshake, and log the result.
185
+ ```bash
186
+ npm run handshake -- --host www.google.com
187
+ ```
188
+
189
+ if you want to test `javascriptcore` compatibility, you can run the [jsc](/src/tests/jsc.test_mac.ts) test. This will run the tests in a JavaScriptCore environment, which is useful for testing compatibility with an ECMAScript environment that does not support WebCrypto.
190
+ Before you run the `jsc` test, make sure you have the `jsc` binary installed on your system & have built the `jsc` file using the `npm run build:jsc` command.
191
+
192
+ ## Updating CA certificates
193
+ ```bash
194
+ npm run update:root-ca
195
+ ```
196
+
197
+ ## Contributing to Our Project
198
+
199
+ We're excited that you're interested in contributing to our project! Before you get started, please take a moment to review the following guidelines.
200
+
201
+ ## Code of Conduct
202
+
203
+ Please read and follow our [Code of Conduct](https://github.com/reclaimprotocol/.github/blob/main/Code-of-Conduct.md) to ensure a positive and inclusive environment for all contributors.
204
+
205
+ ## Security
206
+
207
+ If you discover any security-related issues, please refer to our [Security Policy](https://github.com/reclaimprotocol/.github/blob/main/SECURITY.md) for information on how to responsibly disclose vulnerabilities.
208
+
209
+ ## Contributor License Agreement
210
+
211
+ Before contributing to this project, please read and sign our [Contributor License Agreement (CLA)](https://github.com/reclaimprotocol/.github/blob/main/CLA.md).
212
+
213
+ ## Indie Hackers
214
+
215
+ For Indie Hackers: [Check out our guidelines and potential grant opportunities](https://github.com/reclaimprotocol/.github/blob/main/Indie-Hackers.md)
216
+
217
+ ## License
218
+
219
+ This project is licensed under a [custom license](https://github.com/reclaimprotocol/.github/blob/main/LICENSE). By contributing to this project, you agree that your contributions will be licensed under its terms.
220
+
221
+ Thank you for your contributions!
@@ -0,0 +1,3 @@
1
+ import type { PublicKey as RSAPubKey } from 'micro-rsa-dsa-dh/rsa.js';
2
+ export declare function parseRsaPublicKeyFromAsn1(asn1: Uint8Array): RSAPubKey;
3
+ export declare function bufToUint8Array(buf: ArrayBuffer | Uint8Array): Uint8Array;
@@ -0,0 +1,26 @@
1
+ import { OriginatorPublicKey } from '@peculiar/asn1-cms';
2
+ import { RSAPublicKey } from '@peculiar/asn1-rsa';
3
+ import { AsnParser } from '@peculiar/asn1-schema';
4
+ export function parseRsaPublicKeyFromAsn1(asn1) {
5
+ const parsed = AsnParser.parse(asn1, OriginatorPublicKey);
6
+ const rsaPubKey = AsnParser.parse(parsed.publicKey, RSAPublicKey);
7
+ return {
8
+ e: bufToBigint(bufToUint8Array(rsaPubKey.publicExponent)),
9
+ n: bufToBigint(bufToUint8Array(rsaPubKey.modulus)),
10
+ };
11
+ }
12
+ export function bufToUint8Array(buf) {
13
+ if (buf instanceof Uint8Array) {
14
+ return buf;
15
+ }
16
+ return new Uint8Array(buf);
17
+ }
18
+ const BITS = 8n;
19
+ function bufToBigint(buf) {
20
+ let ret = 0n;
21
+ for (const i of buf.values()) {
22
+ const bi = BigInt(i);
23
+ ret = (ret << BITS) + bi;
24
+ }
25
+ return ret;
26
+ }
@@ -0,0 +1,3 @@
1
+ import type { Crypto } from '../types/index.ts';
2
+ export declare const crypto: Crypto<unknown>;
3
+ export declare function setCryptoImplementation(impl: Crypto<unknown>): void;
@@ -0,0 +1,4 @@
1
+ export const crypto = {};
2
+ export function setCryptoImplementation(impl) {
3
+ Object.assign(crypto, impl);
4
+ }
@@ -0,0 +1 @@
1
+ export declare function randomBytes(length: number): Uint8Array<ArrayBuffer>;
@@ -0,0 +1,9 @@
1
+ export function randomBytes(length) {
2
+ // not the most secure but has to do for an env
3
+ // without crypto.getRandomValues
4
+ const bytes = new Uint8Array(length);
5
+ for (let i = 0; i < length; i++) {
6
+ bytes[i] = Math.floor(Math.random() * 256) % 256;
7
+ }
8
+ return bytes;
9
+ }
@@ -0,0 +1,2 @@
1
+ import type { Crypto } from '../types/index.ts';
2
+ export declare const pureJsCrypto: Crypto<Uint8Array>;
@@ -0,0 +1,144 @@
1
+ import { cbc as aesCbc, gcm as aesGcm } from '@noble/ciphers/aes';
2
+ import { chacha20poly1305 } from '@noble/ciphers/chacha';
3
+ import { x25519 } from '@noble/curves/ed25519';
4
+ import { p256, p384 } from '@noble/curves/nist';
5
+ import { extract } from '@noble/hashes/hkdf';
6
+ import { hmac } from '@noble/hashes/hmac';
7
+ import { sha1 } from '@noble/hashes/legacy';
8
+ import { sha256, sha384 } from '@noble/hashes/sha2';
9
+ import { OriginatorPublicKey } from '@peculiar/asn1-cms';
10
+ import { AsnParser } from '@peculiar/asn1-schema';
11
+ import { mgf1, PKCS1_KEM, PKCS1_SHA256, PKCS1_SHA384, PKCS1_SHA512, PSS } from 'micro-rsa-dsa-dh/rsa.js';
12
+ import { asciiToUint8Array, concatenateUint8Arrays } from "../utils/generics.js";
13
+ import { bufToUint8Array, parseRsaPublicKeyFromAsn1 } from "./common.js";
14
+ import { randomBytes } from "./insecure-rand.js";
15
+ const CURVE_MAP = {
16
+ 'P-256': p256,
17
+ 'P-384': p384,
18
+ 'X25519': x25519
19
+ };
20
+ const AUTH_CIPHER_MAP = {
21
+ 'AES-128-GCM': aesGcm,
22
+ 'AES-256-GCM': aesGcm,
23
+ 'CHACHA20-POLY1305': chacha20poly1305,
24
+ };
25
+ const HASH_MAP = {
26
+ 'SHA-1': sha1,
27
+ 'SHA-256': sha256,
28
+ 'SHA-384': sha384
29
+ };
30
+ const AUTH_TAG_BYTE_LENGTH = 16;
31
+ export const pureJsCrypto = {
32
+ importKey(_, raw) {
33
+ return raw;
34
+ },
35
+ exportKey(key) {
36
+ return key;
37
+ },
38
+ async generateKeyPair(alg) {
39
+ const curve = CURVE_MAP[alg];
40
+ const secretKey = curve.utils.randomSecretKey();
41
+ if (alg === 'P-256' || alg === 'P-384') {
42
+ // @ts-expect-error: need uncompressed public key for TLS
43
+ const pubKey = curve.getPublicKey(secretKey, false);
44
+ return { privKey: secretKey, pubKey };
45
+ }
46
+ return { privKey: secretKey, pubKey: curve.getPublicKey(secretKey) };
47
+ },
48
+ calculateSharedSecret(alg, privateKey, publicKey) {
49
+ const curve = CURVE_MAP[alg];
50
+ if (!curve) {
51
+ throw new Error(`Unsupported algorithm: ${alg}`);
52
+ }
53
+ const secret = curve.getSharedSecret(privateKey, publicKey);
54
+ if (alg === 'P-256' || alg === 'P-384') {
55
+ // from noble curves, the secret is packed with 1 y-coordinate byte
56
+ // so we need to remove the first byte
57
+ return secret.slice(1); // remove the first byte
58
+ }
59
+ return secret;
60
+ },
61
+ randomBytes: randomBytes,
62
+ asymmetricEncrypt(cipherSuite, { publicKey, data }) {
63
+ if (cipherSuite !== 'RSA-PCKS1_5') {
64
+ throw new Error(`Unsupported cipher suite ${cipherSuite}`);
65
+ }
66
+ return PKCS1_KEM.encrypt(parseRsaPublicKeyFromAsn1(publicKey), data);
67
+ },
68
+ encrypt(cipherSuite, { key, iv, data }) {
69
+ if (cipherSuite !== 'AES-128-CBC') {
70
+ throw new Error(`Unsupported cipher suite: ${cipherSuite}`);
71
+ }
72
+ const cipher = aesCbc(key, iv, { disablePadding: true });
73
+ return cipher.encrypt(data);
74
+ },
75
+ decrypt(cipherSuite, { key, iv, data }) {
76
+ if (cipherSuite !== 'AES-128-CBC') {
77
+ throw new Error(`Unsupported cipher suite: ${cipherSuite}`);
78
+ }
79
+ const cipher = aesCbc(key, iv, { disablePadding: true });
80
+ const decrypted = cipher.decrypt(data);
81
+ return decrypted;
82
+ },
83
+ authenticatedEncrypt(cipherSuite, { key, iv, data, aead }) {
84
+ const cipher = AUTH_CIPHER_MAP[cipherSuite](key, iv, aead);
85
+ const ciphertext = cipher.encrypt(data);
86
+ return {
87
+ ciphertext: ciphertext.slice(0, -AUTH_TAG_BYTE_LENGTH),
88
+ authTag: ciphertext.slice(-AUTH_TAG_BYTE_LENGTH),
89
+ };
90
+ },
91
+ authenticatedDecrypt(cipherSuite, { key, iv, data, aead, authTag }) {
92
+ const cipher = AUTH_CIPHER_MAP[cipherSuite](key, iv, aead);
93
+ const decrypted = cipher.decrypt(concatenateUint8Arrays([data, authTag]));
94
+ return { plaintext: decrypted };
95
+ },
96
+ verify(alg, { data, signature, publicKey }) {
97
+ if (alg === 'ECDSA-SECP384R1-SHA384'
98
+ || alg === 'ECDSA-SECP384R1-SHA256'
99
+ || alg === 'ECDSA-SECP256R1-SHA384'
100
+ || alg === 'ECDSA-SECP256R1-SHA256') {
101
+ const parsedPubKey = parseAsn1PublicKey(publicKey);
102
+ const curv = alg.includes('P-384') ? p384 : p256;
103
+ return curv
104
+ .verify(signature, data, parsedPubKey, { prehash: true, format: 'der' });
105
+ }
106
+ if (alg === 'RSA-PSS-SHA256') {
107
+ const rsaPubKey = parseRsaPublicKeyFromAsn1(publicKey);
108
+ const pss = PSS(sha256, mgf1(sha256), 32);
109
+ return pss.verify(rsaPubKey, data, signature);
110
+ }
111
+ if (alg === 'RSA-PKCS1-SHA256') {
112
+ const rsaPubKey = parseRsaPublicKeyFromAsn1(publicKey);
113
+ return PKCS1_SHA256.verify(rsaPubKey, data, signature);
114
+ }
115
+ if (alg === 'RSA-PKCS1-SHA384') {
116
+ const rsaPubKey = parseRsaPublicKeyFromAsn1(publicKey);
117
+ return PKCS1_SHA384.verify(rsaPubKey, data, signature);
118
+ }
119
+ if (alg === 'RSA-PKCS1-SHA512') {
120
+ const rsaPubKey = parseRsaPublicKeyFromAsn1(publicKey);
121
+ return PKCS1_SHA512.verify(rsaPubKey, data, signature);
122
+ }
123
+ throw new Error(`Unsupported signature algorithm: ${alg}`);
124
+ },
125
+ hash(alg, data) {
126
+ const hasher = HASH_MAP[alg].create();
127
+ hasher.update(data);
128
+ return hasher.digest();
129
+ },
130
+ hmac(alg, key, data) {
131
+ return hmac(HASH_MAP[alg], key, data);
132
+ },
133
+ extract(alg, hashLength, ikm, salt) {
134
+ salt = typeof salt === 'string' ? asciiToUint8Array(salt) : salt;
135
+ if (!salt.length) {
136
+ salt = new Uint8Array(hashLength).fill(0);
137
+ }
138
+ return extract(HASH_MAP[alg], ikm, salt);
139
+ }
140
+ };
141
+ function parseAsn1PublicKey(pubKey) {
142
+ const parsed = AsnParser.parse(pubKey, OriginatorPublicKey);
143
+ return bufToUint8Array(parsed.publicKey);
144
+ }
@@ -0,0 +1,3 @@
1
+ import type { webcrypto as WebCrypto } from 'crypto';
2
+ import type { Crypto } from '../types/crypto.ts';
3
+ export declare const webcryptoCrypto: Crypto<WebCrypto.CryptoKey>;