@libp2p/crypto 1.0.11 → 1.0.13
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/dist/index.min.js +7 -7
- package/dist/src/aes/cipher-mode.d.ts.map +1 -1
- package/dist/src/aes/cipher-mode.js +2 -2
- package/dist/src/aes/cipher-mode.js.map +1 -1
- package/dist/src/aes/ciphers-browser.d.ts +4 -5
- package/dist/src/aes/ciphers-browser.d.ts.map +1 -1
- package/dist/src/aes/ciphers-browser.js.map +1 -1
- package/dist/src/aes/index.d.ts.map +1 -1
- package/dist/src/ciphers/aes-gcm.browser.d.ts.map +1 -1
- package/dist/src/ciphers/aes-gcm.d.ts.map +1 -1
- package/dist/src/hmac/index-browser.d.ts +1 -1
- package/dist/src/hmac/index-browser.d.ts.map +1 -1
- package/dist/src/hmac/index-browser.js.map +1 -1
- package/dist/src/hmac/index.d.ts +4 -3
- package/dist/src/hmac/index.d.ts.map +1 -1
- package/dist/src/hmac/index.js.map +1 -1
- package/dist/src/keys/ecdh-browser.d.ts.map +1 -1
- package/dist/src/keys/ecdh-browser.js +6 -6
- package/dist/src/keys/ecdh-browser.js.map +1 -1
- package/dist/src/keys/ecdh.js +2 -2
- package/dist/src/keys/ecdh.js.map +1 -1
- package/dist/src/keys/ed25519-browser.d.ts +3 -8
- package/dist/src/keys/ed25519-browser.d.ts.map +1 -1
- package/dist/src/keys/ed25519-browser.js.map +1 -1
- package/dist/src/keys/ed25519-class.d.ts +3 -3
- 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 +3 -8
- package/dist/src/keys/ed25519.d.ts.map +1 -1
- package/dist/src/keys/ed25519.js +16 -3
- package/dist/src/keys/ed25519.js.map +1 -1
- package/dist/src/keys/exporter.d.ts +2 -1
- package/dist/src/keys/exporter.d.ts.map +1 -1
- package/dist/src/keys/exporter.js.map +1 -1
- package/dist/src/keys/importer.d.ts.map +1 -1
- package/dist/src/keys/index.js +4 -4
- package/dist/src/keys/index.js.map +1 -1
- package/dist/src/keys/interface.d.ts +19 -0
- package/dist/src/keys/interface.d.ts.map +1 -1
- package/dist/src/keys/jwk2pem.d.ts +6 -2
- package/dist/src/keys/jwk2pem.d.ts.map +1 -1
- package/dist/src/keys/jwk2pem.js.map +1 -1
- package/dist/src/keys/key-stretcher.d.ts +2 -12
- package/dist/src/keys/key-stretcher.d.ts.map +1 -1
- package/dist/src/keys/key-stretcher.js +3 -3
- package/dist/src/keys/key-stretcher.js.map +1 -1
- package/dist/src/keys/keys.d.ts.map +1 -1
- package/dist/src/keys/keys.js.map +1 -1
- package/dist/src/keys/rsa-browser.d.ts +3 -8
- package/dist/src/keys/rsa-browser.d.ts.map +1 -1
- package/dist/src/keys/rsa-browser.js +2 -2
- package/dist/src/keys/rsa-browser.js.map +1 -1
- package/dist/src/keys/rsa-class.d.ts +5 -5
- package/dist/src/keys/rsa-class.d.ts.map +1 -1
- package/dist/src/keys/rsa-class.js +3 -3
- package/dist/src/keys/rsa-class.js.map +1 -1
- package/dist/src/keys/rsa-utils.d.ts.map +1 -1
- package/dist/src/keys/rsa-utils.js +3 -3
- package/dist/src/keys/rsa-utils.js.map +1 -1
- package/dist/src/keys/rsa.d.ts +3 -4
- package/dist/src/keys/rsa.d.ts.map +1 -1
- package/dist/src/keys/rsa.js +2 -2
- package/dist/src/keys/rsa.js.map +1 -1
- package/dist/src/keys/secp256k1-class.d.ts +2 -1
- package/dist/src/keys/secp256k1-class.d.ts.map +1 -1
- package/dist/src/keys/secp256k1-class.js +3 -3
- package/dist/src/keys/secp256k1-class.js.map +1 -1
- package/dist/src/keys/secp256k1.d.ts.map +1 -1
- package/dist/src/keys/secp256k1.js +6 -6
- package/dist/src/keys/secp256k1.js.map +1 -1
- package/dist/src/pbkdf2.js +2 -2
- package/dist/src/pbkdf2.js.map +1 -1
- package/dist/src/random-bytes.js +2 -2
- package/dist/src/random-bytes.js.map +1 -1
- package/dist/src/util.d.ts.map +1 -1
- package/dist/src/util.js.map +1 -1
- package/dist/typedoc-urls.json +4 -0
- package/package.json +6 -8
- package/src/aes/cipher-mode.ts +3 -3
- package/src/aes/ciphers-browser.ts +6 -2
- package/src/aes/index.ts +1 -1
- package/src/ciphers/aes-gcm.browser.ts +3 -3
- package/src/ciphers/aes-gcm.ts +5 -5
- package/src/hmac/index-browser.ts +2 -2
- package/src/hmac/index.ts +6 -1
- package/src/keys/ecdh-browser.ts +12 -12
- package/src/keys/ecdh.ts +2 -2
- package/src/keys/ed25519-browser.ts +6 -5
- package/src/keys/ed25519-class.ts +23 -22
- package/src/keys/ed25519.ts +25 -9
- package/src/keys/exporter.ts +2 -1
- package/src/keys/importer.ts +1 -1
- package/src/keys/index.ts +6 -6
- package/src/keys/interface.ts +15 -0
- package/src/keys/jwk2pem.ts +8 -3
- package/src/keys/key-stretcher.ts +6 -5
- package/src/keys/keys.ts +1 -1
- package/src/keys/rsa-browser.ts +12 -11
- package/src/keys/rsa-class.ts +24 -23
- package/src/keys/rsa-utils.ts +5 -5
- package/src/keys/rsa.ts +6 -6
- package/src/keys/secp256k1-class.ts +20 -19
- package/src/keys/secp256k1.ts +14 -14
- package/src/pbkdf2.ts +2 -2
- package/src/random-bytes.ts +2 -2
- package/src/util.ts +2 -2
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { CodeError } from '@libp2p/interfaces/errors'
|
|
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
|
+
import type { EnhancedKey, EnhancedKeyPair } from './interface.js'
|
|
5
6
|
|
|
6
7
|
const cipherMap = {
|
|
7
8
|
'AES-128': {
|
|
@@ -22,16 +23,16 @@ const cipherMap = {
|
|
|
22
23
|
* Generates a set of keys for each party by stretching the shared key.
|
|
23
24
|
* (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
|
|
24
25
|
*/
|
|
25
|
-
export async function keyStretcher (cipherType: 'AES-128' | 'AES-256' | 'Blowfish', hash: 'SHA1' | 'SHA256' | 'SHA512', secret: Uint8Array) {
|
|
26
|
+
export async function keyStretcher (cipherType: 'AES-128' | 'AES-256' | 'Blowfish', hash: 'SHA1' | 'SHA256' | 'SHA512', secret: Uint8Array): Promise<EnhancedKeyPair> {
|
|
26
27
|
const cipher = cipherMap[cipherType]
|
|
27
28
|
|
|
28
29
|
if (cipher == null) {
|
|
29
30
|
const allowed = Object.keys(cipherMap).join(' / ')
|
|
30
|
-
throw
|
|
31
|
+
throw new CodeError(`unknown cipher type '${cipherType}'. Must be ${allowed}`, 'ERR_INVALID_CIPHER_TYPE')
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
if (hash == null) {
|
|
34
|
-
throw
|
|
35
|
+
throw new CodeError('missing hash type', 'ERR_MISSING_HASH_TYPE')
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
const cipherKeySize = cipher.keySize
|
|
@@ -64,7 +65,7 @@ export async function keyStretcher (cipherType: 'AES-128' | 'AES-256' | 'Blowfis
|
|
|
64
65
|
const r1 = resultBuffer.subarray(0, half)
|
|
65
66
|
const r2 = resultBuffer.subarray(half, resultLength)
|
|
66
67
|
|
|
67
|
-
const createKey = (res: Uint8Array) => ({
|
|
68
|
+
const createKey = (res: Uint8Array): EnhancedKey => ({
|
|
68
69
|
iv: res.subarray(0, ivSize),
|
|
69
70
|
cipherKey: res.subarray(ivSize, ivSize + cipherKeySize),
|
|
70
71
|
macKey: res.subarray(ivSize + cipherKeySize)
|
package/src/keys/keys.ts
CHANGED
package/src/keys/rsa-browser.ts
CHANGED
|
@@ -4,11 +4,12 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
|
4
4
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
5
5
|
import * as utils from './rsa-utils.js'
|
|
6
6
|
import { jwk2pub, jwk2priv } from './jwk2pem.js'
|
|
7
|
-
import
|
|
7
|
+
import { CodeError } from '@libp2p/interfaces/errors'
|
|
8
|
+
import type { JWKKeyPair } from './interface.js'
|
|
8
9
|
|
|
9
10
|
export { utils }
|
|
10
11
|
|
|
11
|
-
export async function generateKey (bits: number) {
|
|
12
|
+
export async function generateKey (bits: number): Promise<JWKKeyPair> {
|
|
12
13
|
const pair = await webcrypto.get().subtle.generateKey(
|
|
13
14
|
{
|
|
14
15
|
name: 'RSASSA-PKCS1-v1_5',
|
|
@@ -29,7 +30,7 @@ export async function generateKey (bits: number) {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
// Takes a jwk key
|
|
32
|
-
export async function unmarshalPrivateKey (key: JsonWebKey) {
|
|
33
|
+
export async function unmarshalPrivateKey (key: JsonWebKey): Promise<JWKKeyPair> {
|
|
33
34
|
const privateKey = await webcrypto.get().subtle.importKey(
|
|
34
35
|
'jwk',
|
|
35
36
|
key,
|
|
@@ -59,7 +60,7 @@ export async function unmarshalPrivateKey (key: JsonWebKey) {
|
|
|
59
60
|
|
|
60
61
|
export { randomBytes as getRandomValues }
|
|
61
62
|
|
|
62
|
-
export async function hashAndSign (key: JsonWebKey, msg: Uint8Array) {
|
|
63
|
+
export async function hashAndSign (key: JsonWebKey, msg: Uint8Array): Promise<Uint8Array> {
|
|
63
64
|
const privateKey = await webcrypto.get().subtle.importKey(
|
|
64
65
|
'jwk',
|
|
65
66
|
key,
|
|
@@ -80,7 +81,7 @@ export async function hashAndSign (key: JsonWebKey, msg: Uint8Array) {
|
|
|
80
81
|
return new Uint8Array(sig, 0, sig.byteLength)
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
export async function hashAndVerify (key: JsonWebKey, sig: Uint8Array, msg: Uint8Array) {
|
|
84
|
+
export async function hashAndVerify (key: JsonWebKey, sig: Uint8Array, msg: Uint8Array): Promise<boolean> {
|
|
84
85
|
const publicKey = await webcrypto.get().subtle.importKey(
|
|
85
86
|
'jwk',
|
|
86
87
|
key,
|
|
@@ -100,9 +101,9 @@ export async function hashAndVerify (key: JsonWebKey, sig: Uint8Array, msg: Uint
|
|
|
100
101
|
)
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
async function exportKey (pair: CryptoKeyPair) {
|
|
104
|
+
async function exportKey (pair: CryptoKeyPair): Promise<[JsonWebKey, JsonWebKey]> {
|
|
104
105
|
if (pair.privateKey == null || pair.publicKey == null) {
|
|
105
|
-
throw
|
|
106
|
+
throw new CodeError('Private and public key are required', 'ERR_INVALID_PARAMETERS')
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
return await Promise.all([
|
|
@@ -111,7 +112,7 @@ async function exportKey (pair: CryptoKeyPair) {
|
|
|
111
112
|
])
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
async function derivePublicFromPrivate (jwKey: JsonWebKey) {
|
|
115
|
+
async function derivePublicFromPrivate (jwKey: JsonWebKey): Promise<CryptoKey> {
|
|
115
116
|
return await webcrypto.get().subtle.importKey(
|
|
116
117
|
'jwk',
|
|
117
118
|
{
|
|
@@ -140,17 +141,17 @@ Explanation:
|
|
|
140
141
|
|
|
141
142
|
*/
|
|
142
143
|
|
|
143
|
-
function convertKey (key: JsonWebKey, pub: boolean, msg: Uint8Array, handle: (msg: string, key: { encrypt: (msg: string) => string, decrypt: (msg: string) => string}) => string) {
|
|
144
|
+
function convertKey (key: JsonWebKey, pub: boolean, msg: Uint8Array, handle: (msg: string, key: { encrypt: (msg: string) => string, decrypt: (msg: string) => string }) => string): Uint8Array {
|
|
144
145
|
const fkey = pub ? jwk2pub(key) : jwk2priv(key)
|
|
145
146
|
const fmsg = uint8ArrayToString(Uint8Array.from(msg), 'ascii')
|
|
146
147
|
const fomsg = handle(fmsg, fkey)
|
|
147
148
|
return uint8ArrayFromString(fomsg, 'ascii')
|
|
148
149
|
}
|
|
149
150
|
|
|
150
|
-
export function encrypt (key: JsonWebKey, msg: Uint8Array) {
|
|
151
|
+
export function encrypt (key: JsonWebKey, msg: Uint8Array): Uint8Array {
|
|
151
152
|
return convertKey(key, true, msg, (msg, key) => key.encrypt(msg))
|
|
152
153
|
}
|
|
153
154
|
|
|
154
|
-
export function decrypt (key: JsonWebKey, msg: Uint8Array) {
|
|
155
|
+
export function decrypt (key: JsonWebKey, msg: Uint8Array): Uint8Array {
|
|
155
156
|
return convertKey(key, false, msg, (msg, key) => key.decrypt(msg))
|
|
156
157
|
}
|
package/src/keys/rsa-class.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { sha256 } from 'multiformats/hashes/sha2'
|
|
3
|
-
import
|
|
3
|
+
import { CodeError } from '@libp2p/interfaces/errors'
|
|
4
4
|
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
|
|
5
5
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
6
6
|
import 'node-forge/lib/sha512.js'
|
|
@@ -9,6 +9,7 @@ import forge from 'node-forge/lib/forge.js'
|
|
|
9
9
|
import * as crypto from './rsa.js'
|
|
10
10
|
import * as pbm from './keys.js'
|
|
11
11
|
import { exporter } from './exporter.js'
|
|
12
|
+
import type { Multibase } from 'multiformats'
|
|
12
13
|
|
|
13
14
|
export class RsaPublicKey {
|
|
14
15
|
private readonly _key: JsonWebKey
|
|
@@ -17,30 +18,30 @@ export class RsaPublicKey {
|
|
|
17
18
|
this._key = key
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
async verify (data: Uint8Array, sig: Uint8Array) { // eslint-disable-line require-await
|
|
21
|
+
async verify (data: Uint8Array, sig: Uint8Array): Promise<boolean> { // eslint-disable-line require-await
|
|
21
22
|
return await crypto.hashAndVerify(this._key, sig, data)
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
marshal () {
|
|
25
|
+
marshal (): Uint8Array {
|
|
25
26
|
return crypto.utils.jwkToPkix(this._key)
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
get bytes () {
|
|
29
|
+
get bytes (): Uint8Array {
|
|
29
30
|
return pbm.PublicKey.encode({
|
|
30
31
|
Type: pbm.KeyType.RSA,
|
|
31
32
|
Data: this.marshal()
|
|
32
33
|
}).subarray()
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
encrypt (bytes: Uint8Array) {
|
|
36
|
+
encrypt (bytes: Uint8Array): Uint8Array {
|
|
36
37
|
return crypto.encrypt(this._key, bytes)
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
equals (key: any) {
|
|
40
|
+
equals (key: any): boolean {
|
|
40
41
|
return uint8ArrayEquals(this.bytes, key.bytes)
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
async hash () {
|
|
44
|
+
async hash (): Promise<Uint8Array> {
|
|
44
45
|
const { bytes } = await sha256.digest(this.bytes)
|
|
45
46
|
|
|
46
47
|
return bytes
|
|
@@ -56,42 +57,42 @@ export class RsaPrivateKey {
|
|
|
56
57
|
this._publicKey = publicKey
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
genSecret () {
|
|
60
|
+
genSecret (): Uint8Array {
|
|
60
61
|
return crypto.getRandomValues(16)
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
async sign (message: Uint8Array) { // eslint-disable-line require-await
|
|
64
|
+
async sign (message: Uint8Array): Promise<Uint8Array> { // eslint-disable-line require-await
|
|
64
65
|
return await crypto.hashAndSign(this._key, message)
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
get public () {
|
|
68
|
+
get public (): RsaPublicKey {
|
|
68
69
|
if (this._publicKey == null) {
|
|
69
|
-
throw
|
|
70
|
+
throw new CodeError('public key not provided', 'ERR_PUBKEY_NOT_PROVIDED')
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
return new RsaPublicKey(this._publicKey)
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
decrypt (bytes: Uint8Array) {
|
|
76
|
+
decrypt (bytes: Uint8Array): Uint8Array {
|
|
76
77
|
return crypto.decrypt(this._key, bytes)
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
marshal () {
|
|
80
|
+
marshal (): Uint8Array {
|
|
80
81
|
return crypto.utils.jwkToPkcs1(this._key)
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
get bytes () {
|
|
84
|
+
get bytes (): Uint8Array {
|
|
84
85
|
return pbm.PrivateKey.encode({
|
|
85
86
|
Type: pbm.KeyType.RSA,
|
|
86
87
|
Data: this.marshal()
|
|
87
88
|
}).subarray()
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
equals (key: any) {
|
|
91
|
+
equals (key: any): boolean {
|
|
91
92
|
return uint8ArrayEquals(this.bytes, key.bytes)
|
|
92
93
|
}
|
|
93
94
|
|
|
94
|
-
async hash () {
|
|
95
|
+
async hash (): Promise<Uint8Array> {
|
|
95
96
|
const { bytes } = await sha256.digest(this.bytes)
|
|
96
97
|
|
|
97
98
|
return bytes
|
|
@@ -104,7 +105,7 @@ export class RsaPrivateKey {
|
|
|
104
105
|
* The public key is a protobuf encoding containing a type and the DER encoding
|
|
105
106
|
* of the PKCS SubjectPublicKeyInfo.
|
|
106
107
|
*/
|
|
107
|
-
async id () {
|
|
108
|
+
async id (): Promise<string> {
|
|
108
109
|
const hash = await this.public.hash()
|
|
109
110
|
return uint8ArrayToString(hash, 'base58btc')
|
|
110
111
|
}
|
|
@@ -112,7 +113,7 @@ export class RsaPrivateKey {
|
|
|
112
113
|
/**
|
|
113
114
|
* Exports the key into a password protected PEM format
|
|
114
115
|
*/
|
|
115
|
-
async export (password: string, format = 'pkcs-8') { // eslint-disable-line require-await
|
|
116
|
+
async export (password: string, format = 'pkcs-8'): Promise<Multibase<'m'>> { // eslint-disable-line require-await
|
|
116
117
|
if (format === 'pkcs-8') {
|
|
117
118
|
const buffer = new forge.util.ByteBuffer(this.marshal())
|
|
118
119
|
const asn1 = forge.asn1.fromDer(buffer)
|
|
@@ -128,28 +129,28 @@ export class RsaPrivateKey {
|
|
|
128
129
|
} else if (format === 'libp2p-key') {
|
|
129
130
|
return await exporter(this.bytes, password)
|
|
130
131
|
} else {
|
|
131
|
-
throw
|
|
132
|
+
throw new CodeError(`export format '${format}' is not supported`, 'ERR_INVALID_EXPORT_FORMAT')
|
|
132
133
|
}
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
export async function unmarshalRsaPrivateKey (bytes: Uint8Array) {
|
|
137
|
+
export async function unmarshalRsaPrivateKey (bytes: Uint8Array): Promise<RsaPrivateKey> {
|
|
137
138
|
const jwk = crypto.utils.pkcs1ToJwk(bytes)
|
|
138
139
|
const keys = await crypto.unmarshalPrivateKey(jwk)
|
|
139
140
|
return new RsaPrivateKey(keys.privateKey, keys.publicKey)
|
|
140
141
|
}
|
|
141
142
|
|
|
142
|
-
export function unmarshalRsaPublicKey (bytes: Uint8Array) {
|
|
143
|
+
export function unmarshalRsaPublicKey (bytes: Uint8Array): RsaPublicKey {
|
|
143
144
|
const jwk = crypto.utils.pkixToJwk(bytes)
|
|
144
145
|
return new RsaPublicKey(jwk)
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
export async function fromJwk (jwk: JsonWebKey) {
|
|
148
|
+
export async function fromJwk (jwk: JsonWebKey): Promise<RsaPrivateKey> {
|
|
148
149
|
const keys = await crypto.unmarshalPrivateKey(jwk)
|
|
149
150
|
return new RsaPrivateKey(keys.privateKey, keys.publicKey)
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
export async function generateKeyPair (bits: number) {
|
|
153
|
+
export async function generateKeyPair (bits: number): Promise<RsaPrivateKey> {
|
|
153
154
|
const keys = await crypto.generateKey(bits)
|
|
154
155
|
return new RsaPrivateKey(keys.privateKey, keys.publicKey)
|
|
155
156
|
}
|
package/src/keys/rsa-utils.ts
CHANGED
|
@@ -5,7 +5,7 @@ import forge from 'node-forge/lib/forge.js'
|
|
|
5
5
|
import { bigIntegerToUintBase64url, base64urlToBigInteger } from './../util.js'
|
|
6
6
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
7
7
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
8
|
-
import
|
|
8
|
+
import { CodeError } from '@libp2p/interfaces/errors'
|
|
9
9
|
|
|
10
10
|
// Convert a PKCS#1 in ASN1 DER format to a JWK key
|
|
11
11
|
export function pkcs1ToJwk (bytes: Uint8Array): JsonWebKey {
|
|
@@ -28,9 +28,9 @@ export function pkcs1ToJwk (bytes: Uint8Array): JsonWebKey {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// Convert a JWK key into PKCS#1 in ASN1 DER format
|
|
31
|
-
export function jwkToPkcs1 (jwk: JsonWebKey) {
|
|
31
|
+
export function jwkToPkcs1 (jwk: JsonWebKey): Uint8Array {
|
|
32
32
|
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) {
|
|
33
|
-
throw
|
|
33
|
+
throw new CodeError('JWK was missing components', 'ERR_INVALID_PARAMETERS')
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const asn1 = forge.pki.privateKeyToAsn1({
|
|
@@ -60,9 +60,9 @@ export function pkixToJwk (bytes: Uint8Array): JsonWebKey {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// Convert a JWK key to PKCIX in ASN1 DER format
|
|
63
|
-
export function jwkToPkix (jwk: JsonWebKey) {
|
|
63
|
+
export function jwkToPkix (jwk: JsonWebKey): Uint8Array {
|
|
64
64
|
if (jwk.n == null || jwk.e == null) {
|
|
65
|
-
throw
|
|
65
|
+
throw new CodeError('JWK was missing components', 'ERR_INVALID_PARAMETERS')
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
const asn1 = forge.pki.publicKeyToAsn1({
|
package/src/keys/rsa.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from 'crypto'
|
|
2
2
|
import { promisify } from 'util'
|
|
3
|
-
import
|
|
3
|
+
import { CodeError } from '@libp2p/interfaces/errors'
|
|
4
4
|
import randomBytes from '../random-bytes.js'
|
|
5
5
|
import * as utils from './rsa-utils.js'
|
|
6
6
|
import type { JWKKeyPair } from './interface.js'
|
|
@@ -28,7 +28,7 @@ export async function generateKey (bits: number): Promise<JWKKeyPair> { // eslin
|
|
|
28
28
|
// Takes a jwk key
|
|
29
29
|
export async function unmarshalPrivateKey (key: JsonWebKey): Promise<JWKKeyPair> { // eslint-disable-line require-await
|
|
30
30
|
if (key == null) {
|
|
31
|
-
throw
|
|
31
|
+
throw new CodeError('Missing key parameter', 'ERR_MISSING_KEY')
|
|
32
32
|
}
|
|
33
33
|
return {
|
|
34
34
|
privateKey: key,
|
|
@@ -42,14 +42,14 @@ export async function unmarshalPrivateKey (key: JsonWebKey): Promise<JWKKeyPair>
|
|
|
42
42
|
|
|
43
43
|
export { randomBytes as getRandomValues }
|
|
44
44
|
|
|
45
|
-
export async function hashAndSign (key: JsonWebKey, msg: Uint8Array) {
|
|
45
|
+
export async function hashAndSign (key: JsonWebKey, msg: Uint8Array): Promise<Uint8Array> {
|
|
46
46
|
return crypto.createSign('RSA-SHA256')
|
|
47
47
|
.update(msg)
|
|
48
48
|
// @ts-expect-error node types are missing jwk as a format
|
|
49
49
|
.sign({ format: 'jwk', key })
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export async function hashAndVerify (key: JsonWebKey, sig: Uint8Array, msg: Uint8Array) { // eslint-disable-line require-await
|
|
52
|
+
export async function hashAndVerify (key: JsonWebKey, sig: Uint8Array, msg: Uint8Array): Promise<boolean> { // eslint-disable-line require-await
|
|
53
53
|
return crypto.createVerify('RSA-SHA256')
|
|
54
54
|
.update(msg)
|
|
55
55
|
// @ts-expect-error node types are missing jwk as a format
|
|
@@ -58,12 +58,12 @@ export async function hashAndVerify (key: JsonWebKey, sig: Uint8Array, msg: Uint
|
|
|
58
58
|
|
|
59
59
|
const padding = crypto.constants.RSA_PKCS1_PADDING
|
|
60
60
|
|
|
61
|
-
export function encrypt (key: JsonWebKey, bytes: Uint8Array) {
|
|
61
|
+
export function encrypt (key: JsonWebKey, bytes: Uint8Array): Uint8Array {
|
|
62
62
|
// @ts-expect-error node types are missing jwk as a format
|
|
63
63
|
return crypto.publicEncrypt({ format: 'jwk', key, padding }, bytes)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
export function decrypt (key: JsonWebKey, bytes: Uint8Array) {
|
|
66
|
+
export function decrypt (key: JsonWebKey, bytes: Uint8Array): Uint8Array {
|
|
67
67
|
// @ts-expect-error node types are missing jwk as a format
|
|
68
68
|
return crypto.privateDecrypt({ format: 'jwk', key, padding }, bytes)
|
|
69
69
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { sha256 } from 'multiformats/hashes/sha2'
|
|
2
|
-
import
|
|
2
|
+
import { CodeError } from '@libp2p/interfaces/errors'
|
|
3
3
|
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
|
|
4
4
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
5
5
|
import * as crypto from './secp256k1.js'
|
|
6
6
|
import { exporter } from './exporter.js'
|
|
7
7
|
import * as keysProtobuf from './keys.js'
|
|
8
|
+
import type { Multibase } from 'multiformats'
|
|
8
9
|
|
|
9
10
|
export class Secp256k1PublicKey {
|
|
10
11
|
private readonly _key: Uint8Array
|
|
@@ -14,26 +15,26 @@ export class Secp256k1PublicKey {
|
|
|
14
15
|
this._key = key
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
async verify (data: Uint8Array, sig: Uint8Array) {
|
|
18
|
+
async verify (data: Uint8Array, sig: Uint8Array): Promise<boolean> {
|
|
18
19
|
return await crypto.hashAndVerify(this._key, sig, data)
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
marshal () {
|
|
22
|
+
marshal (): Uint8Array {
|
|
22
23
|
return crypto.compressPublicKey(this._key)
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
get bytes () {
|
|
26
|
+
get bytes (): Uint8Array {
|
|
26
27
|
return keysProtobuf.PublicKey.encode({
|
|
27
28
|
Type: keysProtobuf.KeyType.Secp256k1,
|
|
28
29
|
Data: this.marshal()
|
|
29
30
|
}).subarray()
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
equals (key: any) {
|
|
33
|
+
equals (key: any): boolean {
|
|
33
34
|
return uint8ArrayEquals(this.bytes, key.bytes)
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
async hash () {
|
|
37
|
+
async hash (): Promise<Uint8Array> {
|
|
37
38
|
const { bytes } = await sha256.digest(this.bytes)
|
|
38
39
|
|
|
39
40
|
return bytes
|
|
@@ -51,30 +52,30 @@ export class Secp256k1PrivateKey {
|
|
|
51
52
|
crypto.validatePublicKey(this._publicKey)
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
async sign (message: Uint8Array) {
|
|
55
|
+
async sign (message: Uint8Array): Promise<Uint8Array> {
|
|
55
56
|
return await crypto.hashAndSign(this._key, message)
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
get public () {
|
|
59
|
+
get public (): Secp256k1PublicKey {
|
|
59
60
|
return new Secp256k1PublicKey(this._publicKey)
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
marshal () {
|
|
63
|
+
marshal (): Uint8Array {
|
|
63
64
|
return this._key
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
get bytes () {
|
|
67
|
+
get bytes (): Uint8Array {
|
|
67
68
|
return keysProtobuf.PrivateKey.encode({
|
|
68
69
|
Type: keysProtobuf.KeyType.Secp256k1,
|
|
69
70
|
Data: this.marshal()
|
|
70
71
|
}).subarray()
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
equals (key: any) {
|
|
74
|
+
equals (key: any): boolean {
|
|
74
75
|
return uint8ArrayEquals(this.bytes, key.bytes)
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
async hash () {
|
|
78
|
+
async hash (): Promise<Uint8Array> {
|
|
78
79
|
const { bytes } = await sha256.digest(this.bytes)
|
|
79
80
|
|
|
80
81
|
return bytes
|
|
@@ -87,7 +88,7 @@ export class Secp256k1PrivateKey {
|
|
|
87
88
|
* The public key is a protobuf encoding containing a type and the DER encoding
|
|
88
89
|
* of the PKCS SubjectPublicKeyInfo.
|
|
89
90
|
*/
|
|
90
|
-
async id () {
|
|
91
|
+
async id (): Promise<string> {
|
|
91
92
|
const hash = await this.public.hash()
|
|
92
93
|
return uint8ArrayToString(hash, 'base58btc')
|
|
93
94
|
}
|
|
@@ -95,24 +96,24 @@ export class Secp256k1PrivateKey {
|
|
|
95
96
|
/**
|
|
96
97
|
* Exports the key into a password protected `format`
|
|
97
98
|
*/
|
|
98
|
-
async export (password: string, format = 'libp2p-key') {
|
|
99
|
+
async export (password: string, format = 'libp2p-key'): Promise<Multibase<'m'>> {
|
|
99
100
|
if (format === 'libp2p-key') {
|
|
100
101
|
return await exporter(this.bytes, password)
|
|
101
102
|
} else {
|
|
102
|
-
throw
|
|
103
|
+
throw new CodeError(`export format '${format}' is not supported`, 'ERR_INVALID_EXPORT_FORMAT')
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
export function unmarshalSecp256k1PrivateKey (bytes: Uint8Array) {
|
|
108
|
+
export function unmarshalSecp256k1PrivateKey (bytes: Uint8Array): Secp256k1PrivateKey {
|
|
108
109
|
return new Secp256k1PrivateKey(bytes)
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
export function unmarshalSecp256k1PublicKey (bytes: Uint8Array) {
|
|
112
|
+
export function unmarshalSecp256k1PublicKey (bytes: Uint8Array): Secp256k1PublicKey {
|
|
112
113
|
return new Secp256k1PublicKey(bytes)
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
export async function generateKeyPair () {
|
|
116
|
-
const privateKeyBytes =
|
|
116
|
+
export async function generateKeyPair (): Promise<Secp256k1PrivateKey> {
|
|
117
|
+
const privateKeyBytes = crypto.generateKey()
|
|
117
118
|
return new Secp256k1PrivateKey(privateKeyBytes)
|
|
118
119
|
}
|
package/src/keys/secp256k1.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { CodeError } from '@libp2p/interfaces/errors'
|
|
2
2
|
import * as secp from '@noble/secp256k1'
|
|
3
3
|
import { sha256 } from 'multiformats/hashes/sha2'
|
|
4
4
|
|
|
@@ -6,64 +6,64 @@ const PRIVATE_KEY_BYTE_LENGTH = 32
|
|
|
6
6
|
|
|
7
7
|
export { PRIVATE_KEY_BYTE_LENGTH as privateKeyLength }
|
|
8
8
|
|
|
9
|
-
export function generateKey () {
|
|
9
|
+
export function generateKey (): Uint8Array {
|
|
10
10
|
return secp.utils.randomPrivateKey()
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Hash and sign message with private key
|
|
15
15
|
*/
|
|
16
|
-
export async function hashAndSign (key: Uint8Array, msg: Uint8Array) {
|
|
16
|
+
export async function hashAndSign (key: Uint8Array, msg: Uint8Array): Promise<Uint8Array> {
|
|
17
17
|
const { digest } = await sha256.digest(msg)
|
|
18
18
|
try {
|
|
19
19
|
return await secp.sign(digest, key)
|
|
20
20
|
} catch (err) {
|
|
21
|
-
throw
|
|
21
|
+
throw new CodeError(String(err), 'ERR_INVALID_INPUT')
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Hash message and verify signature with public key
|
|
27
27
|
*/
|
|
28
|
-
export async function hashAndVerify (key: Uint8Array, sig: Uint8Array, msg: Uint8Array) {
|
|
28
|
+
export async function hashAndVerify (key: Uint8Array, sig: Uint8Array, msg: Uint8Array): Promise<boolean> {
|
|
29
29
|
try {
|
|
30
30
|
const { digest } = await sha256.digest(msg)
|
|
31
31
|
return secp.verify(sig, digest, key)
|
|
32
32
|
} catch (err) {
|
|
33
|
-
throw
|
|
33
|
+
throw new CodeError(String(err), 'ERR_INVALID_INPUT')
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export function compressPublicKey (key: Uint8Array) {
|
|
37
|
+
export function compressPublicKey (key: Uint8Array): Uint8Array {
|
|
38
38
|
const point = secp.Point.fromHex(key).toRawBytes(true)
|
|
39
39
|
return point
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export function decompressPublicKey (key: Uint8Array) {
|
|
42
|
+
export function decompressPublicKey (key: Uint8Array): Uint8Array {
|
|
43
43
|
const point = secp.Point.fromHex(key).toRawBytes(false)
|
|
44
44
|
return point
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
export function validatePrivateKey (key: Uint8Array) {
|
|
47
|
+
export function validatePrivateKey (key: Uint8Array): void {
|
|
48
48
|
try {
|
|
49
49
|
secp.getPublicKey(key, true)
|
|
50
50
|
} catch (err) {
|
|
51
|
-
throw
|
|
51
|
+
throw new CodeError(String(err), 'ERR_INVALID_PRIVATE_KEY')
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
export function validatePublicKey (key: Uint8Array) {
|
|
55
|
+
export function validatePublicKey (key: Uint8Array): void {
|
|
56
56
|
try {
|
|
57
57
|
secp.Point.fromHex(key)
|
|
58
58
|
} catch (err) {
|
|
59
|
-
throw
|
|
59
|
+
throw new CodeError(String(err), 'ERR_INVALID_PUBLIC_KEY')
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
export function computePublicKey (privateKey: Uint8Array) {
|
|
63
|
+
export function computePublicKey (privateKey: Uint8Array): Uint8Array {
|
|
64
64
|
try {
|
|
65
65
|
return secp.getPublicKey(privateKey, true)
|
|
66
66
|
} catch (err) {
|
|
67
|
-
throw
|
|
67
|
+
throw new CodeError(String(err), 'ERR_INVALID_PRIVATE_KEY')
|
|
68
68
|
}
|
|
69
69
|
}
|
package/src/pbkdf2.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import forgePbkdf2 from 'node-forge/lib/pbkdf2.js'
|
|
3
3
|
// @ts-expect-error types are missing
|
|
4
4
|
import forgeUtil from 'node-forge/lib/util.js'
|
|
5
|
-
import
|
|
5
|
+
import { CodeError } from '@libp2p/interfaces/errors'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Maps an IPFS hash name to its node-forge equivalent.
|
|
@@ -23,7 +23,7 @@ const hashName = {
|
|
|
23
23
|
export default function pbkdf2 (password: string, salt: string, iterations: number, keySize: number, hash: string): string {
|
|
24
24
|
if (hash !== 'sha1' && hash !== 'sha2-256' && hash !== 'sha2-512') {
|
|
25
25
|
const types = Object.keys(hashName).join(' / ')
|
|
26
|
-
throw
|
|
26
|
+
throw new CodeError(`Hash '${hash}' is unknown or not supported. Must be ${types}`, 'ERR_UNSUPPORTED_HASH_TYPE')
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const hasher = hashName[hash]
|
package/src/random-bytes.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { utils } from '@noble/secp256k1'
|
|
2
|
-
import
|
|
2
|
+
import { CodeError } from '@libp2p/interfaces/errors'
|
|
3
3
|
|
|
4
4
|
export default function randomBytes (length: number): Uint8Array {
|
|
5
5
|
if (isNaN(length) || length <= 0) {
|
|
6
|
-
throw
|
|
6
|
+
throw new CodeError('random bytes length must be a Number bigger than 0', 'ERR_INVALID_LENGTH')
|
|
7
7
|
}
|
|
8
8
|
return utils.randomBytes(length)
|
|
9
9
|
}
|
package/src/util.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
|
6
6
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
7
7
|
import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
|
|
8
8
|
|
|
9
|
-
export function bigIntegerToUintBase64url (num: { abs: () => any}, len?: number) {
|
|
9
|
+
export function bigIntegerToUintBase64url (num: { abs: () => any }, len?: number): string {
|
|
10
10
|
// Call `.abs()` to convert to unsigned
|
|
11
11
|
let buf = Uint8Array.from(num.abs().toByteArray()) // toByteArray converts to big endian
|
|
12
12
|
|
|
@@ -30,7 +30,7 @@ export function base64urlToBigInteger (str: string): typeof forge.jsbn.BigIntege
|
|
|
30
30
|
return new forge.jsbn.BigInteger(uint8ArrayToString(buf, 'base16'), 16)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export function base64urlToBuffer (str: string, len?: number) {
|
|
33
|
+
export function base64urlToBuffer (str: string, len?: number): Uint8Array {
|
|
34
34
|
let buf = uint8ArrayFromString(str, 'base64urlpad')
|
|
35
35
|
|
|
36
36
|
if (len != null) {
|