@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.
- package/README.md +15 -2
- package/dist/index.min.js +16 -0
- package/dist/src/ciphers/aes-gcm.browser.js +3 -3
- package/dist/src/ciphers/aes-gcm.browser.js.map +1 -1
- package/dist/src/ciphers/aes-gcm.js +5 -5
- package/dist/src/ciphers/aes-gcm.js.map +1 -1
- package/dist/src/keys/ecdh-browser.js +3 -3
- package/dist/src/keys/ecdh-browser.js.map +1 -1
- package/dist/src/keys/ed25519-browser.d.ts +18 -0
- package/dist/src/keys/ed25519-browser.d.ts.map +1 -0
- package/dist/src/keys/ed25519-browser.js +52 -0
- package/dist/src/keys/ed25519-browser.js.map +1 -0
- package/dist/src/keys/ed25519-class.d.ts +2 -1
- package/dist/src/keys/ed25519-class.d.ts.map +1 -1
- package/dist/src/keys/ed25519-class.js +4 -4
- package/dist/src/keys/ed25519-class.js.map +1 -1
- package/dist/src/keys/ed25519.d.ts +4 -3
- package/dist/src/keys/ed25519.d.ts.map +1 -1
- package/dist/src/keys/ed25519.js +73 -18
- package/dist/src/keys/ed25519.js.map +1 -1
- package/dist/src/keys/key-stretcher.js +5 -5
- package/dist/src/keys/key-stretcher.js.map +1 -1
- package/dist/src/keys/rsa.js +1 -1
- package/dist/src/keys/rsa.js.map +1 -1
- package/dist/src/util.js +1 -1
- package/dist/src/util.js.map +1 -1
- package/dist/typedoc-urls.json +22 -0
- package/package.json +4 -2
- package/src/ciphers/aes-gcm.browser.ts +3 -3
- package/src/ciphers/aes-gcm.ts +5 -5
- package/src/keys/ecdh-browser.ts +3 -3
- package/src/keys/ed25519-browser.ts +63 -0
- package/src/keys/ed25519-class.ts +4 -4
- package/src/keys/ed25519.ts +77 -19
- package/src/keys/key-stretcher.ts +5 -5
- package/src/keys/rsa.ts +1 -1
- 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.
|
|
114
|
-
const publicKeyBytes = bytes.
|
|
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.
|
|
120
|
-
const publicKeyBytes = bytes.
|
|
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
|
|
package/src/keys/ed25519.ts
CHANGED
|
@@ -1,23 +1,38 @@
|
|
|
1
|
-
import
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
23
|
+
const key = await keypair('ed25519', {
|
|
24
|
+
publicKeyEncoding: { type: 'spki', format: 'jwk' },
|
|
25
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'jwk' }
|
|
26
|
+
})
|
|
14
27
|
|
|
15
|
-
//
|
|
16
|
-
const
|
|
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
|
|
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 (
|
|
47
|
-
|
|
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
|
|
86
|
+
return crypto.sign(null, msg, obj)
|
|
50
87
|
}
|
|
51
88
|
|
|
52
|
-
export async function hashAndVerify (
|
|
53
|
-
|
|
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.
|
|
65
|
-
const r2 = resultBuffer.
|
|
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.
|
|
69
|
-
cipherKey: res.
|
|
70
|
-
macKey: res.
|
|
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.
|
|
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')
|