This repository has been archived by the owner on Jul 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathed25519.spec.ts
224 lines (184 loc) · 7.67 KB
/
ed25519.spec.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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/* eslint-env mocha */
import { expect } from 'aegir/chai'
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
import * as crypto from '../../src/index.js'
import { Ed25519PrivateKey } from '../../src/keys/ed25519-class.js'
import fixtures from '../fixtures/go-key-ed25519.js'
import { testGarbage } from '../helpers/test-garbage-error-handling.js'
const ed25519 = crypto.keys.supportedKeys.ed25519
/** @typedef {import("libp2p-crypto").PrivateKey} PrivateKey */
describe('ed25519', function () {
this.timeout(20 * 1000)
let key: Ed25519PrivateKey
before(async () => {
const generated = await crypto.keys.generateKeyPair('Ed25519', 512)
if (!(generated instanceof Ed25519PrivateKey)) {
throw new Error('Key was incorrect type')
}
key = generated
})
it('generates a valid key', async () => {
expect(key).to.be.an.instanceof(ed25519.Ed25519PrivateKey)
const digest = await key.hash()
expect(digest).to.have.length(34)
})
it('generates a valid key from seed', async () => {
const seed = crypto.randomBytes(32)
const seededkey = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512)
expect(seededkey).to.be.an.instanceof(ed25519.Ed25519PrivateKey)
const digest = await seededkey.hash()
expect(digest).to.have.length(34)
})
it('generates the same key from the same seed', async () => {
const seed = crypto.randomBytes(32)
const seededkey1 = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512)
const seededkey2 = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed, 512)
expect(seededkey1.equals(seededkey2)).to.eql(true)
expect(seededkey1.public.equals(seededkey2.public)).to.eql(true)
})
it('generates different keys for different seeds', async () => {
const seed1 = crypto.randomBytes(32)
const seededkey1 = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed1, 512)
const seed2 = crypto.randomBytes(32)
const seededkey2 = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed2, 512)
expect(seededkey1.equals(seededkey2)).to.eql(false)
expect(seededkey1.public.equals(seededkey2.public)).to.eql(false)
})
it('signs', async () => {
const text = crypto.randomBytes(512)
const sig = await key.sign(text)
const res = await key.public.verify(text, sig)
expect(res).to.be.eql(true)
})
it('encoding', () => {
const keyMarshal = key.marshal()
const key2 = ed25519.unmarshalEd25519PrivateKey(keyMarshal)
const keyMarshal2 = key2.marshal()
expect(keyMarshal).to.eql(keyMarshal2)
const pk = key.public
const pkMarshal = pk.marshal()
const pk2 = ed25519.unmarshalEd25519PublicKey(pkMarshal)
const pkMarshal2 = pk2.marshal()
expect(pkMarshal).to.eql(pkMarshal2)
})
it('key id', async () => {
const key = await crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey)
const id = await key.id()
expect(id).to.eql('12D3KooWLqLxEfJ9nDdEe8Kh8PFvNPQRYDQBwyL7CMM7HhVd5LsX')
})
it('should export a password encrypted libp2p-key', async () => {
const key = await crypto.keys.generateKeyPair('Ed25519')
if (!(key instanceof Ed25519PrivateKey)) {
throw new Error('Key was incorrect type')
}
const encryptedKey = await key.export('my secret')
// Import the key
const importedKey = await crypto.keys.importKey(encryptedKey, 'my secret')
if (!(importedKey instanceof Ed25519PrivateKey)) {
throw new Error('Key was incorrect type')
}
expect(key.equals(importedKey)).to.equal(true)
})
it('should export a libp2p-key with no password to encrypt', async () => {
const key = await crypto.keys.generateKeyPair('Ed25519')
if (!(key instanceof Ed25519PrivateKey)) {
throw new Error('Key was incorrect type')
}
const encryptedKey = await key.export('')
// Import the key
const importedKey = await crypto.keys.importKey(encryptedKey, '')
if (!(importedKey instanceof Ed25519PrivateKey)) {
throw new Error('Key was incorrect type')
}
expect(key.equals(importedKey)).to.equal(true)
})
it('should fail to import libp2p-key with wrong password', async () => {
const key = await crypto.keys.generateKeyPair('Ed25519')
const encryptedKey = await key.export('my secret', 'libp2p-key')
try {
await crypto.keys.importKey(encryptedKey, 'not my secret')
} catch (err) {
expect(err).to.exist()
return
}
expect.fail('should have thrown')
})
describe('key equals', () => {
it('equals itself', () => {
expect(
key.equals(key)
).to.eql(
true
)
expect(
key.public.equals(key.public)
).to.eql(
true
)
})
it('not equals other key', async () => {
const key2 = await crypto.keys.generateKeyPair('Ed25519', 512)
if (!(key2 instanceof Ed25519PrivateKey)) {
throw new Error('Key was incorrect type')
}
expect(key.equals(key2)).to.eql(false)
expect(key2.equals(key)).to.eql(false)
expect(key.public.equals(key2.public)).to.eql(false)
expect(key2.public.equals(key.public)).to.eql(false)
})
})
it('sign and verify', async () => {
const data = uint8ArrayFromString('hello world')
const sig = await key.sign(data)
const valid = await key.public.verify(data, sig)
expect(valid).to.eql(true)
})
it('sign and verify from seed', async () => {
const seed = new Uint8Array(32).fill(1)
const seededkey = await crypto.keys.generateKeyPairFromSeed('Ed25519', seed)
const data = uint8ArrayFromString('hello world')
const sig = await seededkey.sign(data)
const valid = await seededkey.public.verify(data, sig)
expect(valid).to.eql(true)
})
it('fails to verify for different data', async () => {
const data = uint8ArrayFromString('hello world')
const sig = await key.sign(data)
const valid = await key.public.verify(uint8ArrayFromString('hello'), sig)
expect(valid).to.be.eql(false)
})
describe('throws error instead of crashing', () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
testGarbage('key.verify', key.verify.bind(key), 2)
testGarbage('crypto.keys.unmarshalPrivateKey', crypto.keys.unmarshalPrivateKey.bind(crypto.keys))
})
describe('go interop', () => {
// @ts-check
it('verifies with data from go', async () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
const ok = await key.verify(fixtures.verify.data, fixtures.verify.signature)
expect(ok).to.eql(true)
})
it('does not include the redundant public key when marshalling privatekey', async () => {
const key = await crypto.keys.unmarshalPrivateKey(fixtures.redundantPubKey.privateKey)
const bytes = key.marshal()
expect(bytes.length).to.equal(64)
expect(bytes.subarray(32)).to.eql(key.public.marshal())
})
it('verifies with data from go with redundant public key', async () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.redundantPubKey.publicKey)
const ok = await key.verify(fixtures.redundantPubKey.data, fixtures.redundantPubKey.signature)
expect(ok).to.eql(true)
})
it('generates the same signature as go', async () => {
const key = await crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey)
const sig = await key.sign(fixtures.verify.data)
expect(sig).to.eql(fixtures.verify.signature)
})
it('generates the same signature as go with redundant public key', async () => {
const key = await crypto.keys.unmarshalPrivateKey(fixtures.redundantPubKey.privateKey)
const sig = await key.sign(fixtures.redundantPubKey.data)
expect(sig).to.eql(fixtures.redundantPubKey.signature)
})
})
})