@libp2p/crypto 4.1.9 → 5.0.0-18dd3cb26

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 (192) hide show
  1. package/dist/index.min.js +4 -5
  2. package/dist/src/ciphers/aes-gcm.browser.js +1 -1
  3. package/dist/src/ciphers/aes-gcm.browser.js.map +1 -1
  4. package/dist/src/ciphers/index.d.ts +2 -0
  5. package/dist/src/ciphers/index.d.ts.map +1 -0
  6. package/dist/src/ciphers/index.js +2 -0
  7. package/dist/src/ciphers/index.js.map +1 -0
  8. package/dist/src/errors.d.ts +19 -0
  9. package/dist/src/errors.d.ts.map +1 -0
  10. package/dist/src/errors.js +28 -0
  11. package/dist/src/errors.js.map +1 -0
  12. package/dist/src/hmac/{index-browser.d.ts → index.browser.d.ts} +1 -1
  13. package/dist/src/hmac/{index-browser.d.ts.map → index.browser.d.ts.map} +1 -1
  14. package/dist/src/hmac/{index-browser.js → index.browser.js} +2 -2
  15. package/dist/src/hmac/{index-browser.js.map → index.browser.js.map} +1 -1
  16. package/dist/src/keys/ecdh/index.browser.d.ts +4 -0
  17. package/dist/src/keys/ecdh/index.browser.d.ts.map +1 -0
  18. package/dist/src/keys/{ecdh-browser.js → ecdh/index.browser.js} +13 -11
  19. package/dist/src/keys/ecdh/index.browser.js.map +1 -0
  20. package/dist/src/keys/{ecdh.d.ts → ecdh/index.d.ts} +4 -3
  21. package/dist/src/keys/ecdh/index.d.ts.map +1 -0
  22. package/dist/src/keys/{ecdh.js → ecdh/index.js} +4 -4
  23. package/dist/src/keys/ecdh/index.js.map +1 -0
  24. package/dist/src/keys/ed25519/ed25519.d.ts +23 -0
  25. package/dist/src/keys/ed25519/ed25519.d.ts.map +1 -0
  26. package/dist/src/keys/ed25519/ed25519.js +54 -0
  27. package/dist/src/keys/ed25519/ed25519.js.map +1 -0
  28. package/dist/src/keys/{ed25519-browser.d.ts → ed25519/index.browser.d.ts} +2 -2
  29. package/dist/src/keys/ed25519/index.browser.d.ts.map +1 -0
  30. package/dist/src/keys/{ed25519-browser.js → ed25519/index.browser.js} +1 -1
  31. package/dist/src/keys/ed25519/index.browser.js.map +1 -0
  32. package/dist/src/keys/{ed25519.d.ts → ed25519/index.d.ts} +2 -2
  33. package/dist/src/keys/ed25519/index.d.ts.map +1 -0
  34. package/dist/src/keys/{ed25519.js → ed25519/index.js} +1 -1
  35. package/dist/src/keys/ed25519/index.js.map +1 -0
  36. package/dist/src/keys/ed25519/utils.d.ts +7 -0
  37. package/dist/src/keys/ed25519/utils.d.ts.map +1 -0
  38. package/dist/src/keys/ed25519/utils.js +36 -0
  39. package/dist/src/keys/ed25519/utils.js.map +1 -0
  40. package/dist/src/keys/ephemeral-keys.d.ts +2 -2
  41. package/dist/src/keys/ephemeral-keys.d.ts.map +1 -1
  42. package/dist/src/keys/ephemeral-keys.js +2 -2
  43. package/dist/src/keys/ephemeral-keys.js.map +1 -1
  44. package/dist/src/keys/index.d.ts +33 -36
  45. package/dist/src/keys/index.d.ts.map +1 -1
  46. package/dist/src/keys/index.js +93 -83
  47. package/dist/src/keys/index.js.map +1 -1
  48. package/dist/src/keys/key-stretcher.d.ts.map +1 -1
  49. package/dist/src/keys/key-stretcher.js +9 -7
  50. package/dist/src/keys/key-stretcher.js.map +1 -1
  51. package/dist/src/keys/keys.d.ts +4 -4
  52. package/dist/src/keys/keys.d.ts.map +1 -1
  53. package/dist/src/keys/keys.js +21 -15
  54. package/dist/src/keys/keys.js.map +1 -1
  55. package/dist/src/keys/rsa/index.browser.d.ts +11 -0
  56. package/dist/src/keys/rsa/index.browser.d.ts.map +1 -0
  57. package/dist/src/keys/{rsa-browser.js → rsa/index.browser.js} +10 -39
  58. package/dist/src/keys/rsa/index.browser.js.map +1 -0
  59. package/dist/src/keys/rsa/index.d.ts +11 -0
  60. package/dist/src/keys/rsa/index.d.ts.map +1 -0
  61. package/dist/src/keys/{rsa.js → rsa/index.js} +8 -22
  62. package/dist/src/keys/rsa/index.js.map +1 -0
  63. package/dist/src/keys/rsa/rsa.d.ts +28 -0
  64. package/dist/src/keys/rsa/rsa.d.ts.map +1 -0
  65. package/dist/src/keys/rsa/rsa.js +65 -0
  66. package/dist/src/keys/rsa/rsa.js.map +1 -0
  67. package/dist/src/keys/rsa/utils.d.ts +34 -0
  68. package/dist/src/keys/rsa/utils.d.ts.map +1 -0
  69. package/dist/src/keys/rsa/utils.js +193 -0
  70. package/dist/src/keys/rsa/utils.js.map +1 -0
  71. package/dist/src/keys/secp256k1/index.browser.d.ts +10 -0
  72. package/dist/src/keys/secp256k1/index.browser.d.ts.map +1 -0
  73. package/dist/src/keys/secp256k1/index.browser.js +41 -0
  74. package/dist/src/keys/secp256k1/index.browser.js.map +1 -0
  75. package/dist/src/keys/secp256k1/index.d.ts +10 -0
  76. package/dist/src/keys/secp256k1/index.d.ts.map +1 -0
  77. package/dist/src/keys/secp256k1/index.js +47 -0
  78. package/dist/src/keys/secp256k1/index.js.map +1 -0
  79. package/dist/src/keys/secp256k1/secp256k1.d.ts +24 -0
  80. package/dist/src/keys/secp256k1/secp256k1.d.ts.map +1 -0
  81. package/dist/src/keys/secp256k1/secp256k1.js +53 -0
  82. package/dist/src/keys/secp256k1/secp256k1.js.map +1 -0
  83. package/dist/src/keys/secp256k1/utils.d.ts +13 -0
  84. package/dist/src/keys/secp256k1/utils.d.ts.map +1 -0
  85. package/dist/src/keys/secp256k1/utils.js +53 -0
  86. package/dist/src/keys/secp256k1/utils.js.map +1 -0
  87. package/dist/src/pbkdf2.js +2 -2
  88. package/dist/src/pbkdf2.js.map +1 -1
  89. package/dist/src/random-bytes.js +2 -2
  90. package/dist/src/random-bytes.js.map +1 -1
  91. package/dist/src/webcrypto/index.d.ts +3 -0
  92. package/dist/src/webcrypto/index.d.ts.map +1 -0
  93. package/dist/src/webcrypto/index.js +3 -0
  94. package/dist/src/webcrypto/index.js.map +1 -0
  95. package/dist/src/{webcrypto-browser.d.ts → webcrypto/webcrypto.browser.d.ts} +1 -1
  96. package/dist/src/webcrypto/webcrypto.browser.d.ts.map +1 -0
  97. package/dist/src/{webcrypto-browser.js → webcrypto/webcrypto.browser.js} +4 -3
  98. package/dist/src/webcrypto/webcrypto.browser.js.map +1 -0
  99. package/dist/src/webcrypto/webcrypto.d.ts.map +1 -0
  100. package/dist/src/webcrypto/webcrypto.js.map +1 -0
  101. package/package.json +16 -8
  102. package/src/ciphers/aes-gcm.browser.ts +1 -1
  103. package/src/ciphers/index.ts +1 -0
  104. package/src/errors.ts +29 -0
  105. package/src/hmac/{index-browser.ts → index.browser.ts} +1 -1
  106. package/src/keys/{ecdh-browser.ts → ecdh/index.browser.ts} +16 -13
  107. package/src/keys/{ecdh.ts → ecdh/index.ts} +6 -4
  108. package/src/keys/ed25519/ed25519.ts +68 -0
  109. package/src/keys/{ed25519-browser.ts → ed25519/index.browser.ts} +1 -1
  110. package/src/keys/{ed25519.ts → ed25519/index.ts} +1 -1
  111. package/src/keys/ed25519/utils.ts +42 -0
  112. package/src/keys/ephemeral-keys.ts +2 -2
  113. package/src/keys/index.ts +110 -92
  114. package/src/keys/key-stretcher.ts +15 -8
  115. package/src/keys/keys.proto +1 -1
  116. package/src/keys/keys.ts +21 -16
  117. package/src/keys/{rsa-browser.ts → rsa/index.browser.ts} +10 -56
  118. package/src/keys/{rsa.ts → rsa/index.ts} +8 -23
  119. package/src/keys/rsa/rsa.ts +83 -0
  120. package/src/keys/rsa/utils.ts +235 -0
  121. package/src/keys/secp256k1/index.browser.ts +45 -0
  122. package/src/keys/secp256k1/index.ts +51 -0
  123. package/src/keys/secp256k1/secp256k1.ts +68 -0
  124. package/src/keys/secp256k1/utils.ts +63 -0
  125. package/src/pbkdf2.ts +2 -2
  126. package/src/random-bytes.ts +2 -2
  127. package/src/webcrypto/index.ts +3 -0
  128. package/src/webcrypto/webcrypto.browser.ts +23 -0
  129. package/dist/src/keys/ecdh-browser.d.ts +0 -3
  130. package/dist/src/keys/ecdh-browser.d.ts.map +0 -1
  131. package/dist/src/keys/ecdh-browser.js.map +0 -1
  132. package/dist/src/keys/ecdh.d.ts.map +0 -1
  133. package/dist/src/keys/ecdh.js.map +0 -1
  134. package/dist/src/keys/ed25519-browser.d.ts.map +0 -1
  135. package/dist/src/keys/ed25519-browser.js.map +0 -1
  136. package/dist/src/keys/ed25519-class.d.ts +0 -42
  137. package/dist/src/keys/ed25519-class.d.ts.map +0 -1
  138. package/dist/src/keys/ed25519-class.js +0 -133
  139. package/dist/src/keys/ed25519-class.js.map +0 -1
  140. package/dist/src/keys/ed25519.d.ts.map +0 -1
  141. package/dist/src/keys/ed25519.js.map +0 -1
  142. package/dist/src/keys/exporter.d.ts +0 -8
  143. package/dist/src/keys/exporter.d.ts.map +0 -1
  144. package/dist/src/keys/exporter.js +0 -13
  145. package/dist/src/keys/exporter.js.map +0 -1
  146. package/dist/src/keys/importer.d.ts +0 -7
  147. package/dist/src/keys/importer.d.ts.map +0 -1
  148. package/dist/src/keys/importer.js +0 -13
  149. package/dist/src/keys/importer.js.map +0 -1
  150. package/dist/src/keys/rsa-browser.d.ts +0 -12
  151. package/dist/src/keys/rsa-browser.d.ts.map +0 -1
  152. package/dist/src/keys/rsa-browser.js.map +0 -1
  153. package/dist/src/keys/rsa-class.d.ts +0 -46
  154. package/dist/src/keys/rsa-class.d.ts.map +0 -1
  155. package/dist/src/keys/rsa-class.js +0 -135
  156. package/dist/src/keys/rsa-class.js.map +0 -1
  157. package/dist/src/keys/rsa-utils.d.ts +0 -20
  158. package/dist/src/keys/rsa-utils.d.ts.map +0 -1
  159. package/dist/src/keys/rsa-utils.js +0 -330
  160. package/dist/src/keys/rsa-utils.js.map +0 -1
  161. package/dist/src/keys/rsa.d.ts +0 -12
  162. package/dist/src/keys/rsa.d.ts.map +0 -1
  163. package/dist/src/keys/rsa.js.map +0 -1
  164. package/dist/src/keys/secp256k1-browser.d.ts +0 -18
  165. package/dist/src/keys/secp256k1-browser.d.ts.map +0 -1
  166. package/dist/src/keys/secp256k1-browser.js +0 -78
  167. package/dist/src/keys/secp256k1-browser.js.map +0 -1
  168. package/dist/src/keys/secp256k1-class.d.ts +0 -39
  169. package/dist/src/keys/secp256k1-class.d.ts.map +0 -1
  170. package/dist/src/keys/secp256k1-class.js +0 -109
  171. package/dist/src/keys/secp256k1-class.js.map +0 -1
  172. package/dist/src/keys/secp256k1.d.ts +0 -18
  173. package/dist/src/keys/secp256k1.d.ts.map +0 -1
  174. package/dist/src/keys/secp256k1.js +0 -84
  175. package/dist/src/keys/secp256k1.js.map +0 -1
  176. package/dist/src/webcrypto-browser.d.ts.map +0 -1
  177. package/dist/src/webcrypto-browser.js.map +0 -1
  178. package/dist/src/webcrypto.d.ts.map +0 -1
  179. package/dist/src/webcrypto.js.map +0 -1
  180. package/dist/typedoc-urls.json +0 -40
  181. package/src/keys/ed25519-class.ts +0 -160
  182. package/src/keys/exporter.ts +0 -14
  183. package/src/keys/importer.ts +0 -13
  184. package/src/keys/rsa-class.ts +0 -172
  185. package/src/keys/rsa-utils.ts +0 -408
  186. package/src/keys/secp256k1-browser.ts +0 -87
  187. package/src/keys/secp256k1-class.ts +0 -133
  188. package/src/keys/secp256k1.ts +0 -93
  189. package/src/webcrypto-browser.ts +0 -24
  190. /package/dist/src/{webcrypto.d.ts → webcrypto/webcrypto.d.ts} +0 -0
  191. /package/dist/src/{webcrypto.js → webcrypto/webcrypto.js} +0 -0
  192. /package/src/{webcrypto.ts → webcrypto/webcrypto.ts} +0 -0
@@ -1,408 +0,0 @@
1
- import { CodeError } from '@libp2p/interface'
2
- import { pbkdf2Async } from '@noble/hashes/pbkdf2'
3
- import { sha512 } from '@noble/hashes/sha512'
4
- import * as asn1js from 'asn1js'
5
- import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
6
- import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
7
- import randomBytes from '../random-bytes.js'
8
- import webcrypto from '../webcrypto.js'
9
- import { type RsaPrivateKey, unmarshalRsaPrivateKey } from './rsa-class.js'
10
-
11
- /**
12
- * Convert a PKCS#1 in ASN1 DER format to a JWK key
13
- */
14
- export function pkcs1ToJwk (bytes: Uint8Array): JsonWebKey {
15
- const { result } = asn1js.fromBER(bytes)
16
-
17
- // @ts-expect-error this looks fragile but DER is a canonical format so we are
18
- // safe to have deeply property chains like this
19
- const values: asn1js.Integer[] = result.valueBlock.value
20
-
21
- const key = {
22
- n: uint8ArrayToString(bnToBuf(values[1].toBigInt()), 'base64url'),
23
- e: uint8ArrayToString(bnToBuf(values[2].toBigInt()), 'base64url'),
24
- d: uint8ArrayToString(bnToBuf(values[3].toBigInt()), 'base64url'),
25
- p: uint8ArrayToString(bnToBuf(values[4].toBigInt()), 'base64url'),
26
- q: uint8ArrayToString(bnToBuf(values[5].toBigInt()), 'base64url'),
27
- dp: uint8ArrayToString(bnToBuf(values[6].toBigInt()), 'base64url'),
28
- dq: uint8ArrayToString(bnToBuf(values[7].toBigInt()), 'base64url'),
29
- qi: uint8ArrayToString(bnToBuf(values[8].toBigInt()), 'base64url'),
30
- kty: 'RSA',
31
- alg: 'RS256'
32
- }
33
-
34
- return key
35
- }
36
-
37
- /**
38
- * Convert a JWK key into PKCS#1 in ASN1 DER format
39
- */
40
- export function jwkToPkcs1 (jwk: JsonWebKey): Uint8Array {
41
- if (jwk.n == null || jwk.e == null || jwk.d == null || jwk.p == null || jwk.q == null || jwk.dp == null || jwk.dq == null || jwk.qi == null) {
42
- throw new CodeError('JWK was missing components', 'ERR_INVALID_PARAMETERS')
43
- }
44
-
45
- const root = new asn1js.Sequence({
46
- value: [
47
- new asn1js.Integer({ value: 0 }),
48
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.n, 'base64url'))),
49
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.e, 'base64url'))),
50
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.d, 'base64url'))),
51
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.p, 'base64url'))),
52
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.q, 'base64url'))),
53
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.dp, 'base64url'))),
54
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.dq, 'base64url'))),
55
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.qi, 'base64url')))
56
- ]
57
- })
58
-
59
- const der = root.toBER()
60
-
61
- return new Uint8Array(der, 0, der.byteLength)
62
- }
63
-
64
- /**
65
- * Convert a PKCIX in ASN1 DER format to a JWK key
66
- */
67
- export function pkixToJwk (bytes: Uint8Array): JsonWebKey {
68
- const { result } = asn1js.fromBER(bytes)
69
-
70
- // @ts-expect-error this looks fragile but DER is a canonical format so we are
71
- // safe to have deeply property chains like this
72
- const values: asn1js.Integer[] = result.valueBlock.value[1].valueBlock.value[0].valueBlock.value
73
-
74
- return {
75
- kty: 'RSA',
76
- n: uint8ArrayToString(bnToBuf(values[0].toBigInt()), 'base64url'),
77
- e: uint8ArrayToString(bnToBuf(values[1].toBigInt()), 'base64url')
78
- }
79
- }
80
-
81
- /**
82
- * Convert a JWK key to PKCIX in ASN1 DER format
83
- */
84
- export function jwkToPkix (jwk: JsonWebKey): Uint8Array {
85
- if (jwk.n == null || jwk.e == null) {
86
- throw new CodeError('JWK was missing components', 'ERR_INVALID_PARAMETERS')
87
- }
88
-
89
- const root = new asn1js.Sequence({
90
- value: [
91
- new asn1js.Sequence({
92
- value: [
93
- // rsaEncryption
94
- new asn1js.ObjectIdentifier({
95
- value: '1.2.840.113549.1.1.1'
96
- }),
97
- new asn1js.Null()
98
- ]
99
- }),
100
- // this appears to be a bug in asn1js.js - this should really be a Sequence
101
- // and not a BitString but it generates the same bytes as node-forge so 🤷‍♂️
102
- new asn1js.BitString({
103
- valueHex: new asn1js.Sequence({
104
- value: [
105
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.n, 'base64url'))),
106
- asn1js.Integer.fromBigInt(bufToBn(uint8ArrayFromString(jwk.e, 'base64url')))
107
- ]
108
- }).toBER()
109
- })
110
- ]
111
- })
112
-
113
- const der = root.toBER()
114
-
115
- return new Uint8Array(der, 0, der.byteLength)
116
- }
117
-
118
- function bnToBuf (bn: bigint): Uint8Array {
119
- let hex = bn.toString(16)
120
-
121
- if (hex.length % 2 > 0) {
122
- hex = `0${hex}`
123
- }
124
-
125
- const len = hex.length / 2
126
- const u8 = new Uint8Array(len)
127
-
128
- let i = 0
129
- let j = 0
130
-
131
- while (i < len) {
132
- u8[i] = parseInt(hex.slice(j, j + 2), 16)
133
- i += 1
134
- j += 2
135
- }
136
-
137
- return u8
138
- }
139
-
140
- function bufToBn (u8: Uint8Array): bigint {
141
- const hex: string[] = []
142
-
143
- u8.forEach(function (i) {
144
- let h = i.toString(16)
145
-
146
- if (h.length % 2 > 0) {
147
- h = `0${h}`
148
- }
149
-
150
- hex.push(h)
151
- })
152
-
153
- return BigInt('0x' + hex.join(''))
154
- }
155
-
156
- const SALT_LENGTH = 16
157
- const KEY_SIZE = 32
158
- const ITERATIONS = 10000
159
-
160
- export async function exportToPem (privateKey: RsaPrivateKey, password: string): Promise<string> {
161
- const crypto = webcrypto.get()
162
-
163
- // PrivateKeyInfo
164
- const keyWrapper = new asn1js.Sequence({
165
- value: [
166
- // version (0)
167
- new asn1js.Integer({ value: 0 }),
168
-
169
- // privateKeyAlgorithm
170
- new asn1js.Sequence({
171
- value: [
172
- // rsaEncryption OID
173
- new asn1js.ObjectIdentifier({
174
- value: '1.2.840.113549.1.1.1'
175
- }),
176
- new asn1js.Null()
177
- ]
178
- }),
179
-
180
- // PrivateKey
181
- new asn1js.OctetString({
182
- valueHex: privateKey.marshal()
183
- })
184
- ]
185
- })
186
-
187
- const keyBuf = keyWrapper.toBER()
188
- const keyArr = new Uint8Array(keyBuf, 0, keyBuf.byteLength)
189
- const salt = randomBytes(SALT_LENGTH)
190
-
191
- const encryptionKey = await pbkdf2Async(
192
- sha512,
193
- password,
194
- salt, {
195
- c: ITERATIONS,
196
- dkLen: KEY_SIZE
197
- }
198
- )
199
-
200
- const iv = randomBytes(16)
201
- const cryptoKey = await crypto.subtle.importKey('raw', encryptionKey, 'AES-CBC', false, ['encrypt'])
202
- const encrypted = await crypto.subtle.encrypt({
203
- name: 'AES-CBC',
204
- iv
205
- }, cryptoKey, keyArr)
206
-
207
- const pbkdf2Params = new asn1js.Sequence({
208
- value: [
209
- // salt
210
- new asn1js.OctetString({ valueHex: salt }),
211
-
212
- // iteration count
213
- new asn1js.Integer({ value: ITERATIONS }),
214
-
215
- // key length
216
- new asn1js.Integer({ value: KEY_SIZE }),
217
-
218
- // AlgorithmIdentifier
219
- new asn1js.Sequence({
220
- value: [
221
- // hmacWithSHA512
222
- new asn1js.ObjectIdentifier({ value: '1.2.840.113549.2.11' }),
223
- new asn1js.Null()
224
- ]
225
- })
226
- ]
227
- })
228
-
229
- const encryptionAlgorithm = new asn1js.Sequence({
230
- value: [
231
- // pkcs5PBES2
232
- new asn1js.ObjectIdentifier({
233
- value: '1.2.840.113549.1.5.13'
234
- }),
235
- new asn1js.Sequence({
236
- value: [
237
- // keyDerivationFunc
238
- new asn1js.Sequence({
239
- value: [
240
- // pkcs5PBKDF2
241
- new asn1js.ObjectIdentifier({
242
- value: '1.2.840.113549.1.5.12'
243
- }),
244
- // PBKDF2-params
245
- pbkdf2Params
246
- ]
247
- }),
248
-
249
- // encryptionScheme
250
- new asn1js.Sequence({
251
- value: [
252
- // aes256-CBC
253
- new asn1js.ObjectIdentifier({
254
- value: '2.16.840.1.101.3.4.1.42'
255
- }),
256
- // iv
257
- new asn1js.OctetString({
258
- valueHex: iv
259
- })
260
- ]
261
- })
262
- ]
263
- })
264
- ]
265
- })
266
-
267
- const finalWrapper = new asn1js.Sequence({
268
- value: [
269
- encryptionAlgorithm,
270
- new asn1js.OctetString({ valueHex: encrypted })
271
- ]
272
- })
273
-
274
- const finalWrapperBuf = finalWrapper.toBER()
275
- const finalWrapperArr = new Uint8Array(finalWrapperBuf, 0, finalWrapperBuf.byteLength)
276
-
277
- return [
278
- '-----BEGIN ENCRYPTED PRIVATE KEY-----',
279
- ...uint8ArrayToString(finalWrapperArr, 'base64pad').split(/(.{64})/).filter(Boolean),
280
- '-----END ENCRYPTED PRIVATE KEY-----'
281
- ].join('\n')
282
- }
283
-
284
- export async function importFromPem (pem: string, password: string): Promise<RsaPrivateKey> {
285
- const crypto = webcrypto.get()
286
- let plaintext: Uint8Array
287
-
288
- if (pem.includes('-----BEGIN ENCRYPTED PRIVATE KEY-----')) {
289
- const key = uint8ArrayFromString(
290
- pem
291
- .replace('-----BEGIN ENCRYPTED PRIVATE KEY-----', '')
292
- .replace('-----END ENCRYPTED PRIVATE KEY-----', '')
293
- .replace(/\n/g, '')
294
- .trim(),
295
- 'base64pad'
296
- )
297
-
298
- const { result } = asn1js.fromBER(key)
299
-
300
- const {
301
- iv,
302
- salt,
303
- iterations,
304
- keySize,
305
- cipherText
306
- } = findEncryptedPEMData(result)
307
-
308
- const encryptionKey = await pbkdf2Async(
309
- sha512,
310
- password,
311
- salt, {
312
- c: iterations,
313
- dkLen: keySize
314
- }
315
- )
316
-
317
- const cryptoKey = await crypto.subtle.importKey('raw', encryptionKey, 'AES-CBC', false, ['decrypt'])
318
- const decrypted = toUint8Array(await crypto.subtle.decrypt({
319
- name: 'AES-CBC',
320
- iv
321
- }, cryptoKey, cipherText))
322
-
323
- const { result: decryptedResult } = asn1js.fromBER(decrypted)
324
- plaintext = findPEMData(decryptedResult)
325
- } else if (pem.includes('-----BEGIN PRIVATE KEY-----')) {
326
- const key = uint8ArrayFromString(
327
- pem
328
- .replace('-----BEGIN PRIVATE KEY-----', '')
329
- .replace('-----END PRIVATE KEY-----', '')
330
- .replace(/\n/g, '')
331
- .trim(),
332
- 'base64pad'
333
- )
334
-
335
- const { result } = asn1js.fromBER(key)
336
-
337
- plaintext = findPEMData(result)
338
- } else {
339
- throw new CodeError('Could not parse private key from PEM data', 'ERR_INVALID_PARAMETERS')
340
- }
341
-
342
- return unmarshalRsaPrivateKey(plaintext)
343
- }
344
-
345
- function findEncryptedPEMData (root: any): { cipherText: Uint8Array, iv: Uint8Array, salt: Uint8Array, iterations: number, keySize: number } {
346
- const encryptionAlgorithm = root.valueBlock.value[0]
347
- const scheme = encryptionAlgorithm.valueBlock.value[0].toString()
348
-
349
- if (scheme !== 'OBJECT IDENTIFIER : 1.2.840.113549.1.5.13') {
350
- throw new CodeError('Only pkcs5PBES2 encrypted private keys are supported', 'ERR_INVALID_PARAMS')
351
- }
352
-
353
- const keyDerivationFunc = encryptionAlgorithm.valueBlock.value[1].valueBlock.value[0]
354
- const keyDerivationFuncName = keyDerivationFunc.valueBlock.value[0].toString()
355
-
356
- if (keyDerivationFuncName !== 'OBJECT IDENTIFIER : 1.2.840.113549.1.5.12') {
357
- throw new CodeError('Only pkcs5PBKDF2 key derivation functions are supported', 'ERR_INVALID_PARAMS')
358
- }
359
-
360
- const pbkdf2Params = keyDerivationFunc.valueBlock.value[1]
361
-
362
- const salt = toUint8Array(pbkdf2Params.valueBlock.value[0].getValue())
363
-
364
- let iterations = ITERATIONS
365
- let keySize = KEY_SIZE
366
-
367
- if (pbkdf2Params.valueBlock.value.length === 3) {
368
- iterations = Number((pbkdf2Params.valueBlock.value[1] as asn1js.Integer).toBigInt())
369
- keySize = Number((pbkdf2Params.valueBlock.value[2]).toBigInt())
370
- } else if (pbkdf2Params.valueBlock.value.length === 2) {
371
- throw new CodeError('Could not derive key size and iterations from PEM file - please use @libp2p/rsa to re-import your key', 'ERR_INVALID_PARAMS')
372
- }
373
-
374
- const encryptionScheme = encryptionAlgorithm.valueBlock.value[1].valueBlock.value[1]
375
- const encryptionSchemeName = encryptionScheme.valueBlock.value[0].toString()
376
-
377
- if (encryptionSchemeName === 'OBJECT IDENTIFIER : 1.2.840.113549.3.7') {
378
- // des-EDE3-CBC
379
- } else if (encryptionSchemeName === 'OBJECT IDENTIFIER : 1.3.14.3.2.7') {
380
- // des-CBC
381
- } else if (encryptionSchemeName === 'OBJECT IDENTIFIER : 2.16.840.1.101.3.4.1.2') {
382
- // aes128-CBC
383
- } else if (encryptionSchemeName === 'OBJECT IDENTIFIER : 2.16.840.1.101.3.4.1.22') {
384
- // aes192-CBC
385
- } else if (encryptionSchemeName === 'OBJECT IDENTIFIER : 2.16.840.1.101.3.4.1.42') {
386
- // aes256-CBC
387
- } else {
388
- throw new CodeError('Only AES-CBC encryption schemes are supported', 'ERR_INVALID_PARAMS')
389
- }
390
-
391
- const iv = toUint8Array(encryptionScheme.valueBlock.value[1].getValue())
392
-
393
- return {
394
- cipherText: toUint8Array(root.valueBlock.value[1].getValue()),
395
- salt,
396
- iterations,
397
- keySize,
398
- iv
399
- }
400
- }
401
-
402
- function findPEMData (seq: any): Uint8Array {
403
- return toUint8Array(seq.valueBlock.value[2].getValue())
404
- }
405
-
406
- function toUint8Array (buf: ArrayBuffer): Uint8Array {
407
- return new Uint8Array(buf, 0, buf.byteLength)
408
- }
@@ -1,87 +0,0 @@
1
- import { CodeError } from '@libp2p/interface'
2
- import { secp256k1 as secp } from '@noble/curves/secp256k1'
3
- import { sha256 } from 'multiformats/hashes/sha2'
4
- import { isPromise } from '../util.js'
5
- import type { Uint8ArrayList } from 'uint8arraylist'
6
-
7
- const PRIVATE_KEY_BYTE_LENGTH = 32
8
-
9
- export { PRIVATE_KEY_BYTE_LENGTH as privateKeyLength }
10
-
11
- export function generateKey (): Uint8Array {
12
- return secp.utils.randomPrivateKey()
13
- }
14
-
15
- /**
16
- * Hash and sign message with private key
17
- */
18
- export function hashAndSign (key: Uint8Array, msg: Uint8Array | Uint8ArrayList): Uint8Array | Promise<Uint8Array> {
19
- const p = sha256.digest(msg instanceof Uint8Array ? msg : msg.subarray())
20
-
21
- if (isPromise(p)) {
22
- return p.then(({ digest }) => secp.sign(digest, key).toDERRawBytes())
23
- .catch(err => {
24
- throw new CodeError(String(err), 'ERR_INVALID_INPUT')
25
- })
26
- }
27
-
28
- try {
29
- return secp.sign(p.digest, key).toDERRawBytes()
30
- } catch (err) {
31
- throw new CodeError(String(err), 'ERR_INVALID_INPUT')
32
- }
33
- }
34
-
35
- /**
36
- * Hash message and verify signature with public key
37
- */
38
- export function hashAndVerify (key: Uint8Array, sig: Uint8Array, msg: Uint8Array | Uint8ArrayList): boolean | Promise<boolean> {
39
- const p = sha256.digest(msg instanceof Uint8Array ? msg : msg.subarray())
40
-
41
- if (isPromise(p)) {
42
- return p.then(({ digest }) => secp.verify(sig, digest, key))
43
- .catch(err => {
44
- throw new CodeError(String(err), 'ERR_INVALID_INPUT')
45
- })
46
- }
47
-
48
- try {
49
- return secp.verify(sig, p.digest, key)
50
- } catch (err) {
51
- throw new CodeError(String(err), 'ERR_INVALID_INPUT')
52
- }
53
- }
54
-
55
- export function compressPublicKey (key: Uint8Array): Uint8Array {
56
- const point = secp.ProjectivePoint.fromHex(key).toRawBytes(true)
57
- return point
58
- }
59
-
60
- export function decompressPublicKey (key: Uint8Array): Uint8Array {
61
- const point = secp.ProjectivePoint.fromHex(key).toRawBytes(false)
62
- return point
63
- }
64
-
65
- export function validatePrivateKey (key: Uint8Array): void {
66
- try {
67
- secp.getPublicKey(key, true)
68
- } catch (err) {
69
- throw new CodeError(String(err), 'ERR_INVALID_PRIVATE_KEY')
70
- }
71
- }
72
-
73
- export function validatePublicKey (key: Uint8Array): void {
74
- try {
75
- secp.ProjectivePoint.fromHex(key)
76
- } catch (err) {
77
- throw new CodeError(String(err), 'ERR_INVALID_PUBLIC_KEY')
78
- }
79
- }
80
-
81
- export function computePublicKey (privateKey: Uint8Array): Uint8Array {
82
- try {
83
- return secp.getPublicKey(privateKey, true)
84
- } catch (err) {
85
- throw new CodeError(String(err), 'ERR_INVALID_PRIVATE_KEY')
86
- }
87
- }
@@ -1,133 +0,0 @@
1
- import { CodeError } from '@libp2p/interface'
2
- import { sha256 } from 'multiformats/hashes/sha2'
3
- import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
4
- import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
5
- import { isPromise } from '../util.js'
6
- import { exporter } from './exporter.js'
7
- import * as keysProtobuf from './keys.js'
8
- import * as crypto from './secp256k1.js'
9
- import type { PublicKey, PrivateKey } from '@libp2p/interface'
10
- import type { Multibase } from 'multiformats'
11
- import type { Uint8ArrayList } from 'uint8arraylist'
12
-
13
- export class Secp256k1PublicKey implements PublicKey<'secp256k1'> {
14
- private readonly _key: Uint8Array
15
-
16
- constructor (key: Uint8Array) {
17
- crypto.validatePublicKey(key)
18
- this._key = key
19
- }
20
-
21
- verify (data: Uint8Array | Uint8ArrayList, sig: Uint8Array): boolean {
22
- return crypto.hashAndVerify(this._key, sig, data)
23
- }
24
-
25
- marshal (): Uint8Array {
26
- return crypto.compressPublicKey(this._key)
27
- }
28
-
29
- get bytes (): Uint8Array {
30
- return keysProtobuf.PublicKey.encode({
31
- Type: keysProtobuf.KeyType.Secp256k1,
32
- Data: this.marshal()
33
- }).subarray()
34
- }
35
-
36
- equals (key: any): boolean {
37
- return uint8ArrayEquals(this.bytes, key.bytes)
38
- }
39
-
40
- async hash (): Promise<Uint8Array> {
41
- const p = sha256.digest(this.bytes)
42
- let bytes: Uint8Array
43
-
44
- if (isPromise(p)) {
45
- ({ bytes } = await p)
46
- } else {
47
- bytes = p.bytes
48
- }
49
-
50
- return bytes
51
- }
52
- }
53
-
54
- export class Secp256k1PrivateKey implements PrivateKey<'secp256k1'> {
55
- private readonly _key: Uint8Array
56
- private readonly _publicKey: Uint8Array
57
-
58
- constructor (key: Uint8Array, publicKey?: Uint8Array) {
59
- this._key = key
60
- this._publicKey = publicKey ?? crypto.computePublicKey(key)
61
- crypto.validatePrivateKey(this._key)
62
- crypto.validatePublicKey(this._publicKey)
63
- }
64
-
65
- sign (message: Uint8Array | Uint8ArrayList): Uint8Array | Promise<Uint8Array> {
66
- return crypto.hashAndSign(this._key, message)
67
- }
68
-
69
- get public (): Secp256k1PublicKey {
70
- return new Secp256k1PublicKey(this._publicKey)
71
- }
72
-
73
- marshal (): Uint8Array {
74
- return this._key
75
- }
76
-
77
- get bytes (): Uint8Array {
78
- return keysProtobuf.PrivateKey.encode({
79
- Type: keysProtobuf.KeyType.Secp256k1,
80
- Data: this.marshal()
81
- }).subarray()
82
- }
83
-
84
- equals (key: any): boolean {
85
- return uint8ArrayEquals(this.bytes, key.bytes)
86
- }
87
-
88
- hash (): Uint8Array | Promise<Uint8Array> {
89
- const p = sha256.digest(this.bytes)
90
-
91
- if (isPromise(p)) {
92
- return p.then(({ bytes }) => bytes)
93
- }
94
-
95
- return p.bytes
96
- }
97
-
98
- /**
99
- * Gets the ID of the key.
100
- *
101
- * The key id is the base58 encoding of the SHA-256 multihash of its public key.
102
- * The public key is a protobuf encoding containing a type and the DER encoding
103
- * of the PKCS SubjectPublicKeyInfo.
104
- */
105
- async id (): Promise<string> {
106
- const hash = await this.public.hash()
107
- return uint8ArrayToString(hash, 'base58btc')
108
- }
109
-
110
- /**
111
- * Exports the key into a password protected `format`
112
- */
113
- async export (password: string, format = 'libp2p-key'): Promise<Multibase<'m'>> {
114
- if (format === 'libp2p-key') {
115
- return exporter(this.bytes, password)
116
- } else {
117
- throw new CodeError(`export format '${format}' is not supported`, 'ERR_INVALID_EXPORT_FORMAT')
118
- }
119
- }
120
- }
121
-
122
- export function unmarshalSecp256k1PrivateKey (bytes: Uint8Array): Secp256k1PrivateKey {
123
- return new Secp256k1PrivateKey(bytes)
124
- }
125
-
126
- export function unmarshalSecp256k1PublicKey (bytes: Uint8Array): Secp256k1PublicKey {
127
- return new Secp256k1PublicKey(bytes)
128
- }
129
-
130
- export async function generateKeyPair (): Promise<Secp256k1PrivateKey> {
131
- const privateKeyBytes = crypto.generateKey()
132
- return new Secp256k1PrivateKey(privateKeyBytes)
133
- }