@libp2p/crypto 4.1.9-dd7b329c4 → 4.1.9-e1ca9cced

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 (191) 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/src/keys/ed25519-class.ts +0 -160
  181. package/src/keys/exporter.ts +0 -14
  182. package/src/keys/importer.ts +0 -13
  183. package/src/keys/rsa-class.ts +0 -172
  184. package/src/keys/rsa-utils.ts +0 -408
  185. package/src/keys/secp256k1-browser.ts +0 -87
  186. package/src/keys/secp256k1-class.ts +0 -133
  187. package/src/keys/secp256k1.ts +0 -93
  188. package/src/webcrypto-browser.ts +0 -24
  189. /package/dist/src/{webcrypto.d.ts → webcrypto/webcrypto.d.ts} +0 -0
  190. /package/dist/src/{webcrypto.js → webcrypto/webcrypto.js} +0 -0
  191. /package/src/{webcrypto.ts → webcrypto/webcrypto.ts} +0 -0
package/src/keys/index.ts CHANGED
@@ -10,141 +10,159 @@
10
10
  * For encryption / decryption support, RSA keys should be used.
11
11
  */
12
12
 
13
- import { CodeError } from '@libp2p/interface'
14
- import * as Ed25519 from './ed25519-class.js'
15
- import generateEphemeralKeyPair from './ephemeral-keys.js'
16
- import { importer } from './importer.js'
17
- import { keyStretcher } from './key-stretcher.js'
18
- import * as keysPBM from './keys.js'
19
- import * as RSA from './rsa-class.js'
20
- import { importFromPem } from './rsa-utils.js'
21
- import * as Secp256k1 from './secp256k1-class.js'
22
- import type { PrivateKey, PublicKey, KeyType as KeyTypes } from '@libp2p/interface'
23
-
24
- export { keyStretcher }
25
- export { generateEphemeralKeyPair }
26
- export { keysPBM }
27
-
28
- export type { KeyTypes }
29
-
30
- export { RsaPrivateKey, RsaPublicKey, MAX_RSA_KEY_SIZE } from './rsa-class.js'
31
- export { Ed25519PrivateKey, Ed25519PublicKey } from './ed25519-class.js'
32
- export { Secp256k1PrivateKey, Secp256k1PublicKey } from './secp256k1-class.js'
33
- export type { JWKKeyPair } from './interface.js'
34
-
35
- export const supportedKeys = {
36
- rsa: RSA,
37
- ed25519: Ed25519,
38
- secp256k1: Secp256k1
39
- }
13
+ import { UnsupportedKeyTypeError } from '@libp2p/interface'
14
+ import { generateEd25519KeyPair, generateEd25519KeyPairFromSeed, unmarshalEd25519PrivateKey, unmarshalEd25519PublicKey } from './ed25519/utils.js'
15
+ import * as pb from './keys.js'
16
+ import { pkcs1ToRSAPrivateKey, pkixToRSAPublicKey, generateRSAKeyPair } from './rsa/utils.js'
17
+ import { generateSecp256k1KeyPair, unmarshalSecp256k1PrivateKey, unmarshalSecp256k1PublicKey } from './secp256k1/utils.js'
18
+ import type { PrivateKey, PublicKey, KeyType, RSAPrivateKey, Secp256k1PrivateKey, Ed25519PrivateKey, Secp256k1PublicKey, Ed25519PublicKey } from '@libp2p/interface'
19
+ import type { MultihashDigest } from 'multiformats'
40
20
 
41
- function unsupportedKey (type: string): CodeError<Record<string, never>> {
42
- const supported = Object.keys(supportedKeys).join(' / ')
43
- return new CodeError(`invalid or unsupported key type ${type}. Must be ${supported}`, 'ERR_UNSUPPORTED_KEY_TYPE')
44
- }
21
+ export { generateEphemeralKeyPair } from './ecdh/index.js'
22
+ export { keyStretcher } from './key-stretcher.js'
45
23
 
46
- function typeToKey (type: string): typeof RSA | typeof Ed25519 | typeof Secp256k1 {
47
- type = type.toLowerCase()
24
+ /**
25
+ * Generates a keypair of the given type and bitsize
26
+ */
27
+ export async function generateKeyPair (type: 'Ed25519'): Promise<Ed25519PrivateKey>
28
+ export async function generateKeyPair (type: 'secp256k1'): Promise<Secp256k1PrivateKey>
29
+ export async function generateKeyPair (type: 'RSA', bits?: number): Promise<RSAPrivateKey>
30
+ export async function generateKeyPair (type: KeyType, bits?: number): Promise<PrivateKey>
31
+ export async function generateKeyPair (type: KeyType, bits?: number): Promise<unknown> {
32
+ if (type === 'Ed25519') {
33
+ return generateEd25519KeyPair()
34
+ }
48
35
 
49
- if (type === 'rsa' || type === 'ed25519' || type === 'secp256k1') {
50
- return supportedKeys[type]
36
+ if (type === 'secp256k1') {
37
+ return generateSecp256k1KeyPair()
51
38
  }
52
39
 
53
- throw unsupportedKey(type)
54
- }
40
+ if (type === 'RSA') {
41
+ return generateRSAKeyPair(bits ?? 2048)
42
+ }
55
43
 
56
- /**
57
- * Generates a keypair of the given type and bitsize
58
- */
59
- export async function generateKeyPair <T extends KeyTypes> (type: T, bits?: number): Promise<PrivateKey<T>> {
60
- return typeToKey(type).generateKeyPair(bits ?? 2048)
44
+ throw new UnsupportedKeyTypeError()
61
45
  }
62
46
 
63
47
  /**
64
- * Generates a keypair of the given type and bitsize.
48
+ * Generates a keypair of the given type from the passed seed. Currently only
49
+ * supports Ed25519 keys.
65
50
  *
66
51
  * Seed is a 32 byte uint8array
67
52
  */
68
- export async function generateKeyPairFromSeed <T extends KeyTypes> (type: T, seed: Uint8Array, bits?: number): Promise<PrivateKey<T>> {
69
- if (type.toLowerCase() !== 'ed25519') {
70
- throw new CodeError('Seed key derivation is unimplemented for RSA or secp256k1', 'ERR_UNSUPPORTED_KEY_DERIVATION_TYPE')
53
+ export async function generateKeyPairFromSeed (type: 'Ed25519', seed: Uint8Array): Promise<Ed25519PrivateKey>
54
+ export async function generateKeyPairFromSeed <T extends KeyType> (type: T, seed: Uint8Array, bits?: number): Promise<never>
55
+ export async function generateKeyPairFromSeed (type: string, seed: Uint8Array): Promise<unknown> {
56
+ if (type !== 'Ed25519') {
57
+ throw new UnsupportedKeyTypeError('Seed key derivation only supported for Ed25519 keys')
71
58
  }
72
59
 
73
- return Ed25519.generateKeyPairFromSeed(seed)
60
+ return generateEd25519KeyPairFromSeed(seed)
74
61
  }
75
62
 
76
63
  /**
77
64
  * Converts a protobuf serialized public key into its representative object
78
65
  */
79
- export function unmarshalPublicKey <T extends KeyTypes> (buf: Uint8Array): PublicKey<T> {
80
- const decoded = keysPBM.PublicKey.decode(buf)
81
- const data = decoded.Data ?? new Uint8Array()
66
+ export function publicKeyFromProtobuf (buf: Uint8Array): PublicKey {
67
+ const { Type, Data } = pb.PublicKey.decode(buf)
68
+ const data = Data ?? new Uint8Array()
69
+
70
+ switch (Type) {
71
+ case pb.KeyType.RSA:
72
+ return pkixToRSAPublicKey(data)
73
+ case pb.KeyType.Ed25519:
74
+ return unmarshalEd25519PublicKey(data)
75
+ case pb.KeyType.secp256k1:
76
+ return unmarshalSecp256k1PublicKey(data)
77
+ default:
78
+ throw new UnsupportedKeyTypeError()
79
+ }
80
+ }
82
81
 
83
- switch (decoded.Type) {
84
- case keysPBM.KeyType.RSA:
85
- return supportedKeys.rsa.unmarshalRsaPublicKey(data)
86
- case keysPBM.KeyType.Ed25519:
87
- return supportedKeys.ed25519.unmarshalEd25519PublicKey(data)
88
- case keysPBM.KeyType.Secp256k1:
89
- return supportedKeys.secp256k1.unmarshalSecp256k1PublicKey(data)
82
+ /**
83
+ * Creates a public key from the raw key bytes
84
+ */
85
+ export function publicKeyFromRaw (buf: Uint8Array): PublicKey {
86
+ if (buf.byteLength === 32) {
87
+ return unmarshalEd25519PublicKey(buf)
88
+ } else if (buf.byteLength === 34) {
89
+ return unmarshalSecp256k1PublicKey(buf)
90
+ } else {
91
+ return pkixToRSAPublicKey(buf)
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Creates a public key from an identity multihash which contains a protobuf
97
+ * encoded Ed25519 or secp256k1 public key.
98
+ *
99
+ * RSA keys are not supported as in practice we they are not stored in identity
100
+ * multihashes since the hash would be very large.
101
+ */
102
+ export function publicKeyFromMultihash (digest: MultihashDigest<0x0>): Ed25519PublicKey | Secp256k1PublicKey {
103
+ const { Type, Data } = pb.PublicKey.decode(digest.digest)
104
+ const data = Data ?? new Uint8Array()
105
+
106
+ switch (Type) {
107
+ case pb.KeyType.Ed25519:
108
+ return unmarshalEd25519PublicKey(data)
109
+ case pb.KeyType.secp256k1:
110
+ return unmarshalSecp256k1PublicKey(data)
90
111
  default:
91
- throw unsupportedKey(decoded.Type ?? 'unknown')
112
+ throw new UnsupportedKeyTypeError()
92
113
  }
93
114
  }
94
115
 
95
116
  /**
96
117
  * Converts a public key object into a protobuf serialized public key
97
118
  */
98
- export function marshalPublicKey (key: { bytes: Uint8Array }, type?: string): Uint8Array {
99
- type = (type ?? 'rsa').toLowerCase()
100
- typeToKey(type) // check type
101
- return key.bytes
119
+ export function publicKeyToProtobuf (key: PublicKey): Uint8Array {
120
+ return pb.PublicKey.encode({
121
+ Type: pb.KeyType[key.type],
122
+ Data: key.raw
123
+ })
102
124
  }
103
125
 
104
126
  /**
105
127
  * Converts a protobuf serialized private key into its representative object
106
128
  */
107
- export async function unmarshalPrivateKey <T extends KeyTypes> (buf: Uint8Array): Promise<PrivateKey<T>> {
108
- const decoded = keysPBM.PrivateKey.decode(buf)
129
+ export function privateKeyFromProtobuf (buf: Uint8Array): Ed25519PrivateKey | Secp256k1PrivateKey | RSAPrivateKey {
130
+ const decoded = pb.PrivateKey.decode(buf)
109
131
  const data = decoded.Data ?? new Uint8Array()
110
132
 
111
133
  switch (decoded.Type) {
112
- case keysPBM.KeyType.RSA:
113
- return supportedKeys.rsa.unmarshalRsaPrivateKey(data)
114
- case keysPBM.KeyType.Ed25519:
115
- return supportedKeys.ed25519.unmarshalEd25519PrivateKey(data)
116
- case keysPBM.KeyType.Secp256k1:
117
- return supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey(data)
134
+ case pb.KeyType.RSA:
135
+ return pkcs1ToRSAPrivateKey(data)
136
+ case pb.KeyType.Ed25519:
137
+ return unmarshalEd25519PrivateKey(data)
138
+ case pb.KeyType.secp256k1:
139
+ return unmarshalSecp256k1PrivateKey(data)
118
140
  default:
119
- throw unsupportedKey(decoded.Type ?? 'RSA')
141
+ throw new UnsupportedKeyTypeError()
120
142
  }
121
143
  }
122
144
 
123
145
  /**
124
- * Converts a private key object into a protobuf serialized private key
146
+ * Creates a private key from the raw key bytes. For Ed25519 keys this requires
147
+ * the public key to be appended to the private key otherwise we can't
148
+ * differentiate between Ed25519 and secp256k1 keys as they are the same length.
125
149
  */
126
- export function marshalPrivateKey (key: { bytes: Uint8Array }, type?: string): Uint8Array {
127
- type = (type ?? 'rsa').toLowerCase()
128
- typeToKey(type) // check type
129
- return key.bytes
150
+ export function privateKeyFromRaw (buf: Uint8Array): PrivateKey {
151
+ if (buf.byteLength === 64) {
152
+ return unmarshalEd25519PrivateKey(buf)
153
+ } else if (buf.byteLength === 32) {
154
+ return unmarshalSecp256k1PrivateKey(buf)
155
+ } else {
156
+ return pkcs1ToRSAPrivateKey(buf)
157
+ }
130
158
  }
131
159
 
132
160
  /**
133
- * Converts an exported private key into its representative object.
134
- *
135
- * Supported formats are 'pem' (RSA only) and 'libp2p-key'.
161
+ * Converts a private key object into a protobuf serialized private key
136
162
  */
137
- export async function importKey <T extends KeyTypes> (encryptedKey: string, password: string): Promise<PrivateKey<T>> {
138
- try {
139
- const key = await importer(encryptedKey, password)
140
- return await unmarshalPrivateKey(key)
141
- } catch (_) {
142
- // Ignore and try the old pem decrypt
143
- }
144
-
145
- if (!encryptedKey.includes('BEGIN')) {
146
- throw new CodeError('Encrypted key was not a libp2p-key or a PEM file', 'ERR_INVALID_IMPORT_FORMAT')
147
- }
148
-
149
- return importFromPem(encryptedKey, password)
163
+ export function privateKeyToProtobuf (key: PrivateKey): Uint8Array {
164
+ return pb.PrivateKey.encode({
165
+ Type: pb.KeyType[key.type],
166
+ Data: key.raw
167
+ })
150
168
  }
@@ -1,10 +1,15 @@
1
- import { CodeError } from '@libp2p/interface'
1
+ import { InvalidParametersError } from '@libp2p/interface'
2
2
  import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
3
3
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
4
4
  import * as hmac from '../hmac/index.js'
5
5
  import type { EnhancedKey, EnhancedKeyPair } from './interface.js'
6
6
 
7
- const cipherMap = {
7
+ interface Cipher {
8
+ ivSize: number
9
+ keySize: number
10
+ }
11
+
12
+ const cipherMap: Record<string, Cipher> = {
8
13
  'AES-128': {
9
14
  ivSize: 16,
10
15
  keySize: 16
@@ -24,17 +29,19 @@ const cipherMap = {
24
29
  * (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
25
30
  */
26
31
  export async function keyStretcher (cipherType: 'AES-128' | 'AES-256' | 'Blowfish', hash: 'SHA1' | 'SHA256' | 'SHA512', secret: Uint8Array): Promise<EnhancedKeyPair> {
27
- const cipher = cipherMap[cipherType]
32
+ if (cipherType !== 'AES-128' && cipherType !== 'AES-256' && cipherType !== 'Blowfish') {
33
+ throw new InvalidParametersError('Cipher type was missing or unsupported')
34
+ }
28
35
 
29
- if (cipher == null) {
30
- const allowed = Object.keys(cipherMap).join(' / ')
31
- throw new CodeError(`unknown cipher type '${cipherType}'. Must be ${allowed}`, 'ERR_INVALID_CIPHER_TYPE')
36
+ if (hash !== 'SHA1' && hash !== 'SHA256' && hash !== 'SHA512') {
37
+ throw new InvalidParametersError('Hash type was missing or unsupported')
32
38
  }
33
39
 
34
- if (hash == null) {
35
- throw new CodeError('missing hash type', 'ERR_MISSING_HASH_TYPE')
40
+ if (secret == null || !(secret instanceof Uint8Array)) {
41
+ throw new InvalidParametersError('Secret was missing or an incorrect type')
36
42
  }
37
43
 
44
+ const cipher = cipherMap[cipherType]
38
45
  const cipherKeySize = cipher.keySize
39
46
  const ivSize = cipher.ivSize
40
47
  const hmacKeySize = 20
@@ -3,7 +3,7 @@ syntax = "proto3";
3
3
  enum KeyType {
4
4
  RSA = 0;
5
5
  Ed25519 = 1;
6
- Secp256k1 = 2;
6
+ secp256k1 = 2;
7
7
  }
8
8
  message PublicKey {
9
9
  // the proto2 version of this field is "required" which means it will have
package/src/keys/keys.ts CHANGED
@@ -4,20 +4,19 @@
4
4
  /* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
5
5
  /* eslint-disable @typescript-eslint/no-empty-interface */
6
6
 
7
- import { enumeration, encodeMessage, decodeMessage, message } from 'protons-runtime'
8
- import type { Codec } from 'protons-runtime'
7
+ import { type Codec, decodeMessage, type DecodeOptions, encodeMessage, enumeration, message } from 'protons-runtime'
9
8
  import type { Uint8ArrayList } from 'uint8arraylist'
10
9
 
11
10
  export enum KeyType {
12
11
  RSA = 'RSA',
13
12
  Ed25519 = 'Ed25519',
14
- Secp256k1 = 'Secp256k1'
13
+ secp256k1 = 'secp256k1'
15
14
  }
16
15
 
17
16
  enum __KeyTypeValues {
18
17
  RSA = 0,
19
18
  Ed25519 = 1,
20
- Secp256k1 = 2
19
+ secp256k1 = 2
21
20
  }
22
21
 
23
22
  export namespace KeyType {
@@ -53,7 +52,7 @@ export namespace PublicKey {
53
52
  if (opts.lengthDelimited !== false) {
54
53
  w.ldelim()
55
54
  }
56
- }, (reader, length) => {
55
+ }, (reader, length, opts = {}) => {
57
56
  const obj: any = {}
58
57
 
59
58
  const end = length == null ? reader.len : reader.pos + length
@@ -62,15 +61,18 @@ export namespace PublicKey {
62
61
  const tag = reader.uint32()
63
62
 
64
63
  switch (tag >>> 3) {
65
- case 1:
64
+ case 1: {
66
65
  obj.Type = KeyType.codec().decode(reader)
67
66
  break
68
- case 2:
67
+ }
68
+ case 2: {
69
69
  obj.Data = reader.bytes()
70
70
  break
71
- default:
71
+ }
72
+ default: {
72
73
  reader.skipType(tag & 7)
73
74
  break
75
+ }
74
76
  }
75
77
  }
76
78
 
@@ -85,8 +87,8 @@ export namespace PublicKey {
85
87
  return encodeMessage(obj, PublicKey.codec())
86
88
  }
87
89
 
88
- export const decode = (buf: Uint8Array | Uint8ArrayList): PublicKey => {
89
- return decodeMessage(buf, PublicKey.codec())
90
+ export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<PublicKey>): PublicKey => {
91
+ return decodeMessage(buf, PublicKey.codec(), opts)
90
92
  }
91
93
  }
92
94
 
@@ -118,7 +120,7 @@ export namespace PrivateKey {
118
120
  if (opts.lengthDelimited !== false) {
119
121
  w.ldelim()
120
122
  }
121
- }, (reader, length) => {
123
+ }, (reader, length, opts = {}) => {
122
124
  const obj: any = {}
123
125
 
124
126
  const end = length == null ? reader.len : reader.pos + length
@@ -127,15 +129,18 @@ export namespace PrivateKey {
127
129
  const tag = reader.uint32()
128
130
 
129
131
  switch (tag >>> 3) {
130
- case 1:
132
+ case 1: {
131
133
  obj.Type = KeyType.codec().decode(reader)
132
134
  break
133
- case 2:
135
+ }
136
+ case 2: {
134
137
  obj.Data = reader.bytes()
135
138
  break
136
- default:
139
+ }
140
+ default: {
137
141
  reader.skipType(tag & 7)
138
142
  break
143
+ }
139
144
  }
140
145
  }
141
146
 
@@ -150,7 +155,7 @@ export namespace PrivateKey {
150
155
  return encodeMessage(obj, PrivateKey.codec())
151
156
  }
152
157
 
153
- export const decode = (buf: Uint8Array | Uint8ArrayList): PrivateKey => {
154
- return decodeMessage(buf, PrivateKey.codec())
158
+ export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<PrivateKey>): PrivateKey => {
159
+ return decodeMessage(buf, PrivateKey.codec(), opts)
155
160
  }
156
161
  }
@@ -1,14 +1,14 @@
1
- import { CodeError } from '@libp2p/interface'
1
+ import { InvalidParametersError } from '@libp2p/interface'
2
2
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
3
- import randomBytes from '../random-bytes.js'
4
- import webcrypto from '../webcrypto.js'
5
- import * as utils from './rsa-utils.js'
6
- import type { JWKKeyPair } from './interface.js'
3
+ import randomBytes from '../../random-bytes.js'
4
+ import webcrypto from '../../webcrypto/index.js'
5
+ import * as utils from './utils.js'
6
+ import type { JWKKeyPair } from '../interface.js'
7
7
  import type { Uint8ArrayList } from 'uint8arraylist'
8
8
 
9
9
  export { utils }
10
10
 
11
- export async function generateKey (bits: number): Promise<JWKKeyPair> {
11
+ export async function generateRSAKey (bits: number): Promise<JWKKeyPair> {
12
12
  const pair = await webcrypto.get().subtle.generateKey(
13
13
  {
14
14
  name: 'RSASSA-PKCS1-v1_5',
@@ -28,35 +28,6 @@ export async function generateKey (bits: number): Promise<JWKKeyPair> {
28
28
  }
29
29
  }
30
30
 
31
- // Takes a jwk key
32
- export async function unmarshalPrivateKey (key: JsonWebKey): Promise<JWKKeyPair> {
33
- const privateKey = await webcrypto.get().subtle.importKey(
34
- 'jwk',
35
- key,
36
- {
37
- name: 'RSASSA-PKCS1-v1_5',
38
- hash: { name: 'SHA-256' }
39
- },
40
- true,
41
- ['sign']
42
- )
43
-
44
- const pair = [
45
- privateKey,
46
- await derivePublicFromPrivate(key)
47
- ]
48
-
49
- const keys = await exportKey({
50
- privateKey: pair[0],
51
- publicKey: pair[1]
52
- })
53
-
54
- return {
55
- privateKey: keys[0],
56
- publicKey: keys[1]
57
- }
58
- }
59
-
60
31
  export { randomBytes as getRandomValues }
61
32
 
62
33
  export async function hashAndSign (key: JsonWebKey, msg: Uint8Array | Uint8ArrayList): Promise<Uint8Array> {
@@ -102,7 +73,7 @@ export async function hashAndVerify (key: JsonWebKey, sig: Uint8Array, msg: Uint
102
73
 
103
74
  async function exportKey (pair: CryptoKeyPair): Promise<[JsonWebKey, JsonWebKey]> {
104
75
  if (pair.privateKey == null || pair.publicKey == null) {
105
- throw new CodeError('Private and public key are required', 'ERR_INVALID_PARAMETERS')
76
+ throw new InvalidParametersError('Private and public key are required')
106
77
  }
107
78
 
108
79
  return Promise.all([
@@ -111,28 +82,11 @@ async function exportKey (pair: CryptoKeyPair): Promise<[JsonWebKey, JsonWebKey]
111
82
  ])
112
83
  }
113
84
 
114
- async function derivePublicFromPrivate (jwKey: JsonWebKey): Promise<CryptoKey> {
115
- return webcrypto.get().subtle.importKey(
116
- 'jwk',
117
- {
118
- kty: jwKey.kty,
119
- n: jwKey.n,
120
- e: jwKey.e
121
- },
122
- {
123
- name: 'RSASSA-PKCS1-v1_5',
124
- hash: { name: 'SHA-256' }
125
- },
126
- true,
127
- ['verify']
128
- )
129
- }
130
-
131
- export function keySize (jwk: JsonWebKey): number {
85
+ export function rsaKeySize (jwk: JsonWebKey): number {
132
86
  if (jwk.kty !== 'RSA') {
133
- throw new CodeError('invalid key type', 'ERR_INVALID_KEY_TYPE')
87
+ throw new InvalidParametersError('invalid key type')
134
88
  } else if (jwk.n == null) {
135
- throw new CodeError('invalid key modulus', 'ERR_INVALID_KEY_MODULUS')
89
+ throw new InvalidParametersError('invalid key modulus')
136
90
  }
137
91
  const bytes = uint8ArrayFromString(jwk.n, 'base64url')
138
92
  return bytes.length * 8
@@ -1,17 +1,17 @@
1
1
  import crypto from 'crypto'
2
2
  import { promisify } from 'util'
3
- import { CodeError } from '@libp2p/interface'
3
+ import { InvalidParametersError } from '@libp2p/interface'
4
4
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
5
- import randomBytes from '../random-bytes.js'
6
- import * as utils from './rsa-utils.js'
7
- import type { JWKKeyPair } from './interface.js'
5
+ import randomBytes from '../../random-bytes.js'
6
+ import * as utils from './utils.js'
7
+ import type { JWKKeyPair } from '../interface.js'
8
8
  import type { Uint8ArrayList } from 'uint8arraylist'
9
9
 
10
10
  const keypair = promisify(crypto.generateKeyPair)
11
11
 
12
12
  export { utils }
13
13
 
14
- export async function generateKey (bits: number): Promise<JWKKeyPair> {
14
+ export async function generateRSAKey (bits: number): Promise<JWKKeyPair> {
15
15
  // @ts-expect-error node types are missing jwk as a format
16
16
  const key = await keypair('rsa', {
17
17
  modulusLength: bits,
@@ -27,21 +27,6 @@ export async function generateKey (bits: number): Promise<JWKKeyPair> {
27
27
  }
28
28
  }
29
29
 
30
- // Takes a jwk key
31
- export async function unmarshalPrivateKey (key: JsonWebKey): Promise<JWKKeyPair> {
32
- if (key == null) {
33
- throw new CodeError('Missing key parameter', 'ERR_MISSING_KEY')
34
- }
35
- return {
36
- privateKey: key,
37
- publicKey: {
38
- kty: key.kty,
39
- n: key.n,
40
- e: key.e
41
- }
42
- }
43
- }
44
-
45
30
  export { randomBytes as getRandomValues }
46
31
 
47
32
  export async function hashAndSign (key: JsonWebKey, msg: Uint8Array | Uint8ArrayList): Promise<Uint8Array> {
@@ -74,11 +59,11 @@ export async function hashAndVerify (key: JsonWebKey, sig: Uint8Array, msg: Uint
74
59
  return hash.verify({ format: 'jwk', key }, sig)
75
60
  }
76
61
 
77
- export function keySize (jwk: JsonWebKey): number {
62
+ export function rsaKeySize (jwk: JsonWebKey): number {
78
63
  if (jwk.kty !== 'RSA') {
79
- throw new CodeError('invalid key type', 'ERR_INVALID_KEY_TYPE')
64
+ throw new InvalidParametersError('Invalid key type')
80
65
  } else if (jwk.n == null) {
81
- throw new CodeError('invalid key modulus', 'ERR_INVALID_KEY_MODULUS')
66
+ throw new InvalidParametersError('Invalid key modulus')
82
67
  }
83
68
  const modulus = uint8ArrayFromString(jwk.n, 'base64url')
84
69
  return modulus.length * 8
@@ -0,0 +1,83 @@
1
+ import { base58btc } from 'multiformats/bases/base58'
2
+ import { CID } from 'multiformats/cid'
3
+ import { type Digest } from 'multiformats/hashes/digest'
4
+ import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
5
+ import { hashAndSign, utils, hashAndVerify } from './index.js'
6
+ import type { RSAPublicKey as RSAPublicKeyInterface, RSAPrivateKey as RSAPrivateKeyInterface } from '@libp2p/interface'
7
+ import type { Uint8ArrayList } from 'uint8arraylist'
8
+
9
+ export class RSAPublicKey implements RSAPublicKeyInterface {
10
+ public readonly type = 'RSA'
11
+ private readonly _key: JsonWebKey
12
+ private _raw?: Uint8Array
13
+ private readonly _multihash: Digest<18, number>
14
+
15
+ constructor (key: JsonWebKey, digest: Digest<18, number>) {
16
+ this._key = key
17
+ this._multihash = digest
18
+ }
19
+
20
+ get raw (): Uint8Array {
21
+ if (this._raw == null) {
22
+ this._raw = utils.jwkToPkix(this._key)
23
+ }
24
+
25
+ return this._raw
26
+ }
27
+
28
+ toMultihash (): Digest<18, number> {
29
+ return this._multihash
30
+ }
31
+
32
+ toCID (): CID<unknown, 114, 18, 1> {
33
+ return CID.createV1(114, this._multihash)
34
+ }
35
+
36
+ toString (): string {
37
+ return base58btc.encode(this.toMultihash().bytes).substring(1)
38
+ }
39
+
40
+ equals (key?: any): boolean {
41
+ if (key == null || !(key.raw instanceof Uint8Array)) {
42
+ return false
43
+ }
44
+
45
+ return uint8ArrayEquals(this.raw, key.raw)
46
+ }
47
+
48
+ verify (data: Uint8Array | Uint8ArrayList, sig: Uint8Array): boolean | Promise<boolean> {
49
+ return hashAndVerify(this._key, sig, data)
50
+ }
51
+ }
52
+
53
+ export class RSAPrivateKey implements RSAPrivateKeyInterface {
54
+ public readonly type = 'RSA'
55
+ private readonly _key: JsonWebKey
56
+ private _raw?: Uint8Array
57
+ public readonly publicKey: RSAPublicKey
58
+
59
+ constructor (key: JsonWebKey, publicKey: RSAPublicKey) {
60
+ this._key = key
61
+ this.publicKey = publicKey
62
+ }
63
+
64
+ get raw (): Uint8Array {
65
+ if (this._raw == null) {
66
+ this._raw = utils.jwkToPkcs1(this._key)
67
+ }
68
+
69
+ return this._raw
70
+ }
71
+
72
+ equals (key: any): boolean {
73
+ if (key == null || !(key.raw instanceof Uint8Array)) {
74
+ return false
75
+ }
76
+
77
+ return uint8ArrayEquals(this.raw, key.raw)
78
+ }
79
+
80
+ sign (message: Uint8Array | Uint8ArrayList): Uint8Array | Promise<Uint8Array> {
81
+ return hashAndSign(this._key, message)
82
+ }
83
+ }