@libp2p/crypto 1.0.8 → 1.0.10

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 (37) hide show
  1. package/README.md +15 -2
  2. package/dist/index.min.js +16 -0
  3. package/dist/src/ciphers/aes-gcm.browser.js +3 -3
  4. package/dist/src/ciphers/aes-gcm.browser.js.map +1 -1
  5. package/dist/src/ciphers/aes-gcm.js +5 -5
  6. package/dist/src/ciphers/aes-gcm.js.map +1 -1
  7. package/dist/src/keys/ecdh-browser.js +3 -3
  8. package/dist/src/keys/ecdh-browser.js.map +1 -1
  9. package/dist/src/keys/ed25519-browser.d.ts +18 -0
  10. package/dist/src/keys/ed25519-browser.d.ts.map +1 -0
  11. package/dist/src/keys/ed25519-browser.js +52 -0
  12. package/dist/src/keys/ed25519-browser.js.map +1 -0
  13. package/dist/src/keys/ed25519-class.d.ts +2 -1
  14. package/dist/src/keys/ed25519-class.d.ts.map +1 -1
  15. package/dist/src/keys/ed25519-class.js +4 -4
  16. package/dist/src/keys/ed25519-class.js.map +1 -1
  17. package/dist/src/keys/ed25519.d.ts +4 -3
  18. package/dist/src/keys/ed25519.d.ts.map +1 -1
  19. package/dist/src/keys/ed25519.js +73 -18
  20. package/dist/src/keys/ed25519.js.map +1 -1
  21. package/dist/src/keys/key-stretcher.js +5 -5
  22. package/dist/src/keys/key-stretcher.js.map +1 -1
  23. package/dist/src/keys/rsa.js +1 -1
  24. package/dist/src/keys/rsa.js.map +1 -1
  25. package/dist/src/util.js +1 -1
  26. package/dist/src/util.js.map +1 -1
  27. package/dist/typedoc-urls.json +22 -0
  28. package/package.json +4 -2
  29. package/src/ciphers/aes-gcm.browser.ts +3 -3
  30. package/src/ciphers/aes-gcm.ts +5 -5
  31. package/src/keys/ecdh-browser.ts +3 -3
  32. package/src/keys/ed25519-browser.ts +63 -0
  33. package/src/keys/ed25519-class.ts +4 -4
  34. package/src/keys/ed25519.ts +77 -19
  35. package/src/keys/key-stretcher.ts +5 -5
  36. package/src/keys/rsa.ts +1 -1
  37. package/src/util.ts +1 -1
@@ -0,0 +1,63 @@
1
+ import * as ed from '@noble/ed25519'
2
+
3
+ const PUBLIC_KEY_BYTE_LENGTH = 32
4
+ const PRIVATE_KEY_BYTE_LENGTH = 64 // private key is actually 32 bytes but for historical reasons we concat private and public keys
5
+ const KEYS_BYTE_LENGTH = 32
6
+
7
+ export { PUBLIC_KEY_BYTE_LENGTH as publicKeyLength }
8
+ export { PRIVATE_KEY_BYTE_LENGTH as privateKeyLength }
9
+
10
+ export async function generateKey () {
11
+ // the actual private key (32 bytes)
12
+ const privateKeyRaw = ed.utils.randomPrivateKey()
13
+ const publicKey = await ed.getPublicKey(privateKeyRaw)
14
+
15
+ // concatenated the public key to the private key
16
+ const privateKey = concatKeys(privateKeyRaw, publicKey)
17
+
18
+ return {
19
+ privateKey,
20
+ publicKey
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Generate keypair from a 32 byte uint8array
26
+ */
27
+ export async function generateKeyFromSeed (seed: Uint8Array) {
28
+ if (seed.length !== KEYS_BYTE_LENGTH) {
29
+ throw new TypeError('"seed" must be 32 bytes in length.')
30
+ } else if (!(seed instanceof Uint8Array)) {
31
+ throw new TypeError('"seed" must be a node.js Buffer, or Uint8Array.')
32
+ }
33
+
34
+ // based on node forges algorithm, the seed is used directly as private key
35
+ const privateKeyRaw = seed
36
+ const publicKey = await ed.getPublicKey(privateKeyRaw)
37
+
38
+ const privateKey = concatKeys(privateKeyRaw, publicKey)
39
+
40
+ return {
41
+ privateKey,
42
+ publicKey
43
+ }
44
+ }
45
+
46
+ export async function hashAndSign (privateKey: Uint8Array, msg: Uint8Array) {
47
+ const privateKeyRaw = privateKey.subarray(0, KEYS_BYTE_LENGTH)
48
+
49
+ return await ed.sign(msg, privateKeyRaw)
50
+ }
51
+
52
+ export async function hashAndVerify (publicKey: Uint8Array, sig: Uint8Array, msg: Uint8Array) {
53
+ return await ed.verify(sig, msg, publicKey)
54
+ }
55
+
56
+ function concatKeys (privateKeyRaw: Uint8Array, publicKey: Uint8Array) {
57
+ const privateKey = new Uint8Array(PRIVATE_KEY_BYTE_LENGTH)
58
+ for (let i = 0; i < KEYS_BYTE_LENGTH; i++) {
59
+ privateKey[i] = privateKeyRaw[i]
60
+ privateKey[KEYS_BYTE_LENGTH + i] = publicKey[i]
61
+ }
62
+ return privateKey
63
+ }
@@ -110,14 +110,14 @@ export function unmarshalEd25519PrivateKey (bytes: Uint8Array) {
110
110
  // Try the old, redundant public key version
111
111
  if (bytes.length > crypto.privateKeyLength) {
112
112
  bytes = ensureKey(bytes, crypto.privateKeyLength + crypto.publicKeyLength)
113
- const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength)
114
- const publicKeyBytes = bytes.slice(crypto.privateKeyLength, bytes.length)
113
+ const privateKeyBytes = bytes.subarray(0, crypto.privateKeyLength)
114
+ const publicKeyBytes = bytes.subarray(crypto.privateKeyLength, bytes.length)
115
115
  return new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes)
116
116
  }
117
117
 
118
118
  bytes = ensureKey(bytes, crypto.privateKeyLength)
119
- const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength)
120
- const publicKeyBytes = bytes.slice(crypto.publicKeyLength)
119
+ const privateKeyBytes = bytes.subarray(0, crypto.privateKeyLength)
120
+ const publicKeyBytes = bytes.subarray(crypto.publicKeyLength)
121
121
  return new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes)
122
122
  }
123
123
 
@@ -1,23 +1,38 @@
1
- import * as ed from '@noble/ed25519'
1
+ import crypto from 'crypto'
2
+ import { promisify } from 'util'
3
+ import { toString as uint8arrayToString } from 'uint8arrays/to-string'
4
+ import { fromString as uint8arrayFromString } from 'uint8arrays/from-string'
5
+
6
+ const keypair = promisify(crypto.generateKeyPair)
2
7
 
3
8
  const PUBLIC_KEY_BYTE_LENGTH = 32
4
9
  const PRIVATE_KEY_BYTE_LENGTH = 64 // private key is actually 32 bytes but for historical reasons we concat private and public keys
5
10
  const KEYS_BYTE_LENGTH = 32
11
+ const SIGNATURE_BYTE_LENGTH = 64
6
12
 
7
13
  export { PUBLIC_KEY_BYTE_LENGTH as publicKeyLength }
8
14
  export { PRIVATE_KEY_BYTE_LENGTH as privateKeyLength }
9
15
 
16
+ function derivePublicKey (privateKey: Uint8Array) {
17
+ const hash = crypto.createHash('sha512')
18
+ hash.update(privateKey)
19
+ return hash.digest().subarray(32)
20
+ }
21
+
10
22
  export async function generateKey () {
11
- // the actual private key (32 bytes)
12
- const privateKeyRaw = ed.utils.randomPrivateKey()
13
- const publicKey = await ed.getPublicKey(privateKeyRaw)
23
+ const key = await keypair('ed25519', {
24
+ publicKeyEncoding: { type: 'spki', format: 'jwk' },
25
+ privateKeyEncoding: { type: 'pkcs8', format: 'jwk' }
26
+ })
14
27
 
15
- // concatenated the public key to the private key
16
- const privateKey = concatKeys(privateKeyRaw, publicKey)
28
+ // @ts-expect-error node types are missing jwk as a format
29
+ const privateKeyRaw = uint8arrayFromString(key.privateKey.d, 'base64url')
30
+ // @ts-expect-error node types are missing jwk as a format
31
+ const publicKeyRaw = uint8arrayFromString(key.privateKey.x, 'base64url')
17
32
 
18
33
  return {
19
- privateKey,
20
- publicKey
34
+ privateKey: concatKeys(privateKeyRaw, publicKeyRaw),
35
+ publicKey: publicKeyRaw
21
36
  }
22
37
  }
23
38
 
@@ -32,25 +47,68 @@ export async function generateKeyFromSeed (seed: Uint8Array) {
32
47
  }
33
48
 
34
49
  // based on node forges algorithm, the seed is used directly as private key
35
- const privateKeyRaw = seed
36
- const publicKey = await ed.getPublicKey(privateKeyRaw)
37
-
38
- const privateKey = concatKeys(privateKeyRaw, publicKey)
50
+ const publicKeyRaw = derivePublicKey(seed)
39
51
 
40
52
  return {
41
- privateKey,
42
- publicKey
53
+ privateKey: concatKeys(seed, publicKeyRaw),
54
+ publicKey: publicKeyRaw
43
55
  }
44
56
  }
45
57
 
46
- export async function hashAndSign (privateKey: Uint8Array, msg: Uint8Array) {
47
- const privateKeyRaw = privateKey.slice(0, KEYS_BYTE_LENGTH)
58
+ export async function hashAndSign (key: Uint8Array, msg: Uint8Array) {
59
+ if (!(key instanceof Uint8Array)) {
60
+ throw new TypeError('"key" must be a node.js Buffer, or Uint8Array.')
61
+ }
62
+
63
+ let privateKey: Uint8Array
64
+ let publicKey: Uint8Array
65
+
66
+ if (key.byteLength === PRIVATE_KEY_BYTE_LENGTH) {
67
+ privateKey = key.subarray(0, 32)
68
+ publicKey = key.subarray(32)
69
+ } else if (key.byteLength === KEYS_BYTE_LENGTH) {
70
+ privateKey = key.subarray(0, 32)
71
+ publicKey = derivePublicKey(privateKey)
72
+ } else {
73
+ throw new TypeError('"key" must be 64 or 32 bytes in length.')
74
+ }
75
+
76
+ const obj = crypto.createPrivateKey({
77
+ format: 'jwk',
78
+ key: {
79
+ crv: 'Ed25519',
80
+ d: uint8arrayToString(privateKey, 'base64url'),
81
+ x: uint8arrayToString(publicKey, 'base64url'),
82
+ kty: 'OKP'
83
+ }
84
+ })
48
85
 
49
- return await ed.sign(msg, privateKeyRaw)
86
+ return crypto.sign(null, msg, obj)
50
87
  }
51
88
 
52
- export async function hashAndVerify (publicKey: Uint8Array, sig: Uint8Array, msg: Uint8Array) {
53
- return await ed.verify(sig, msg, publicKey)
89
+ export async function hashAndVerify (key: Uint8Array, sig: Uint8Array, msg: Uint8Array) {
90
+ if (key.byteLength !== PUBLIC_KEY_BYTE_LENGTH) {
91
+ throw new TypeError('"key" must be 32 bytes in length.')
92
+ } else if (!(key instanceof Uint8Array)) {
93
+ throw new TypeError('"key" must be a node.js Buffer, or Uint8Array.')
94
+ }
95
+
96
+ if (sig.byteLength !== SIGNATURE_BYTE_LENGTH) {
97
+ throw new TypeError('"sig" must be 64 bytes in length.')
98
+ } else if (!(sig instanceof Uint8Array)) {
99
+ throw new TypeError('"sig" must be a node.js Buffer, or Uint8Array.')
100
+ }
101
+
102
+ const obj = crypto.createPublicKey({
103
+ format: 'jwk',
104
+ key: {
105
+ crv: 'Ed25519',
106
+ x: uint8arrayToString(key, 'base64url'),
107
+ kty: 'OKP'
108
+ }
109
+ })
110
+
111
+ return crypto.verify(null, msg, obj, sig)
54
112
  }
55
113
 
56
114
  function concatKeys (privateKeyRaw: Uint8Array, publicKey: Uint8Array) {
@@ -61,13 +61,13 @@ export async function keyStretcher (cipherType: 'AES-128' | 'AES-256' | 'Blowfis
61
61
 
62
62
  const half = resultLength / 2
63
63
  const resultBuffer = uint8ArrayConcat(result)
64
- const r1 = resultBuffer.slice(0, half)
65
- const r2 = resultBuffer.slice(half, resultLength)
64
+ const r1 = resultBuffer.subarray(0, half)
65
+ const r2 = resultBuffer.subarray(half, resultLength)
66
66
 
67
67
  const createKey = (res: Uint8Array) => ({
68
- iv: res.slice(0, ivSize),
69
- cipherKey: res.slice(ivSize, ivSize + cipherKeySize),
70
- macKey: res.slice(ivSize + cipherKeySize)
68
+ iv: res.subarray(0, ivSize),
69
+ cipherKey: res.subarray(ivSize, ivSize + cipherKeySize),
70
+ macKey: res.subarray(ivSize + cipherKeySize)
71
71
  })
72
72
 
73
73
  return {
package/src/keys/rsa.ts CHANGED
@@ -50,9 +50,9 @@ export async function hashAndSign (key: JsonWebKey, msg: Uint8Array) { // eslint
50
50
  }
51
51
 
52
52
  export async function hashAndVerify (key: JsonWebKey, sig: Uint8Array, msg: Uint8Array) { // eslint-disable-line require-await
53
- // @ts-expect-error node types are missing jwk as a format
54
53
  return crypto.createVerify('RSA-SHA256')
55
54
  .update(msg)
55
+ // @ts-expect-error node types are missing jwk as a format
56
56
  .verify({ format: 'jwk', key }, sig)
57
57
  }
58
58
 
package/src/util.ts CHANGED
@@ -14,7 +14,7 @@ export function bigIntegerToUintBase64url (num: { abs: () => any}, len?: number)
14
14
  // byte if the most significant bit of the number is 1:
15
15
  // https://docs.microsoft.com/en-us/windows/win32/seccertenroll/about-integer
16
16
  // Our number will always be positive so we should remove the leading padding.
17
- buf = buf[0] === 0 ? buf.slice(1) : buf
17
+ buf = buf[0] === 0 ? buf.subarray(1) : buf
18
18
 
19
19
  if (len != null) {
20
20
  if (buf.length > len) throw new Error('byte array longer than desired length')