-
Notifications
You must be signed in to change notification settings - Fork 443
/
index.ts
168 lines (150 loc) · 5.66 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/**
* @packageDocumentation
*
* **Supported Key Types**
*
* The {@link generateKeyPair}, {@link marshalPublicKey}, and {@link marshalPrivateKey} functions accept a string `type` argument.
*
* Currently the `'RSA'`, `'ed25519'`, and `secp256k1` types are supported, although ed25519 and secp256k1 keys support only signing and verification of messages.
*
* For encryption / decryption support, RSA keys should be used.
*/
import { UnsupportedKeyTypeError } from '@libp2p/interface'
import { generateEd25519KeyPair, generateEd25519KeyPairFromSeed, unmarshalEd25519PrivateKey, unmarshalEd25519PublicKey } from './ed25519/utils.js'
import * as pb from './keys.js'
import { pkcs1ToRSAPrivateKey, pkixToRSAPublicKey, generateRSAKeyPair } from './rsa/utils.js'
import { generateSecp256k1KeyPair, unmarshalSecp256k1PrivateKey, unmarshalSecp256k1PublicKey } from './secp256k1/utils.js'
import type { PrivateKey, PublicKey, KeyType, RSAPrivateKey, Secp256k1PrivateKey, Ed25519PrivateKey, Secp256k1PublicKey, Ed25519PublicKey } from '@libp2p/interface'
import type { MultihashDigest } from 'multiformats'
export { generateEphemeralKeyPair } from './ecdh/index.js'
export { keyStretcher } from './key-stretcher.js'
/**
* Generates a keypair of the given type and bitsize
*/
export async function generateKeyPair (type: 'Ed25519'): Promise<Ed25519PrivateKey>
export async function generateKeyPair (type: 'secp256k1'): Promise<Secp256k1PrivateKey>
export async function generateKeyPair (type: 'RSA', bits?: number): Promise<RSAPrivateKey>
export async function generateKeyPair (type: KeyType, bits?: number): Promise<PrivateKey>
export async function generateKeyPair (type: KeyType, bits?: number): Promise<unknown> {
if (type === 'Ed25519') {
return generateEd25519KeyPair()
}
if (type === 'secp256k1') {
return generateSecp256k1KeyPair()
}
if (type === 'RSA') {
return generateRSAKeyPair(bits ?? 2048)
}
throw new UnsupportedKeyTypeError()
}
/**
* Generates a keypair of the given type from the passed seed. Currently only
* supports Ed25519 keys.
*
* Seed is a 32 byte uint8array
*/
export async function generateKeyPairFromSeed (type: 'Ed25519', seed: Uint8Array): Promise<Ed25519PrivateKey>
export async function generateKeyPairFromSeed <T extends KeyType> (type: T, seed: Uint8Array, bits?: number): Promise<never>
export async function generateKeyPairFromSeed (type: string, seed: Uint8Array): Promise<unknown> {
if (type !== 'Ed25519') {
throw new UnsupportedKeyTypeError('Seed key derivation only supported for Ed25519 keys')
}
return generateEd25519KeyPairFromSeed(seed)
}
/**
* Converts a protobuf serialized public key into its representative object
*/
export function publicKeyFromProtobuf (buf: Uint8Array): PublicKey {
const { Type, Data } = pb.PublicKey.decode(buf)
const data = Data ?? new Uint8Array()
switch (Type) {
case pb.KeyType.RSA:
return pkixToRSAPublicKey(data)
case pb.KeyType.Ed25519:
return unmarshalEd25519PublicKey(data)
case pb.KeyType.secp256k1:
return unmarshalSecp256k1PublicKey(data)
default:
throw new UnsupportedKeyTypeError()
}
}
/**
* Creates a public key from the raw key bytes
*/
export function publicKeyFromRaw (buf: Uint8Array): PublicKey {
if (buf.byteLength === 32) {
return unmarshalEd25519PublicKey(buf)
} else if (buf.byteLength === 33) {
return unmarshalSecp256k1PublicKey(buf)
} else {
return pkixToRSAPublicKey(buf)
}
}
/**
* Creates a public key from an identity multihash which contains a protobuf
* encoded Ed25519 or secp256k1 public key.
*
* RSA keys are not supported as in practice we they are not stored in identity
* multihashes since the hash would be very large.
*/
export function publicKeyFromMultihash (digest: MultihashDigest<0x0>): Ed25519PublicKey | Secp256k1PublicKey {
const { Type, Data } = pb.PublicKey.decode(digest.digest)
const data = Data ?? new Uint8Array()
switch (Type) {
case pb.KeyType.Ed25519:
return unmarshalEd25519PublicKey(data)
case pb.KeyType.secp256k1:
return unmarshalSecp256k1PublicKey(data)
default:
throw new UnsupportedKeyTypeError()
}
}
/**
* Converts a public key object into a protobuf serialized public key
*/
export function publicKeyToProtobuf (key: PublicKey): Uint8Array {
return pb.PublicKey.encode({
Type: pb.KeyType[key.type],
Data: key.raw
})
}
/**
* Converts a protobuf serialized private key into its representative object
*/
export function privateKeyFromProtobuf (buf: Uint8Array): Ed25519PrivateKey | Secp256k1PrivateKey | RSAPrivateKey {
const decoded = pb.PrivateKey.decode(buf)
const data = decoded.Data ?? new Uint8Array()
switch (decoded.Type) {
case pb.KeyType.RSA:
return pkcs1ToRSAPrivateKey(data)
case pb.KeyType.Ed25519:
return unmarshalEd25519PrivateKey(data)
case pb.KeyType.secp256k1:
return unmarshalSecp256k1PrivateKey(data)
default:
throw new UnsupportedKeyTypeError()
}
}
/**
* Creates a private key from the raw key bytes. For Ed25519 keys this requires
* the public key to be appended to the private key otherwise we can't
* differentiate between Ed25519 and secp256k1 keys as they are the same length.
*/
export function privateKeyFromRaw (buf: Uint8Array): PrivateKey {
if (buf.byteLength === 64) {
return unmarshalEd25519PrivateKey(buf)
} else if (buf.byteLength === 32) {
return unmarshalSecp256k1PrivateKey(buf)
} else {
return pkcs1ToRSAPrivateKey(buf)
}
}
/**
* Converts a private key object into a protobuf serialized private key
*/
export function privateKeyToProtobuf (key: PrivateKey): Uint8Array {
return pb.PrivateKey.encode({
Type: pb.KeyType[key.type],
Data: key.raw
})
}