3
3
4
4
const { expect } = require ( 'aegir/utils/chai' )
5
5
const { base58btc } = require ( 'multiformats/bases/base58' )
6
+ const { base64urlpad } = require ( 'multiformats/bases/base64' )
6
7
const { fromString : uint8ArrayFromString } = require ( 'uint8arrays/from-string' )
7
8
const { concat : uint8ArrayConcat } = require ( 'uint8arrays/concat' )
8
9
const PeerId = require ( 'peer-id' )
@@ -21,13 +22,18 @@ describe('ipns', function () {
21
22
let ipfsId
22
23
/** @type {import('libp2p-crypto').keys.supportedKeys.rsa.RsaPrivateKey } */
23
24
let rsa
25
+ /** @type {import('libp2p-crypto').keys.supportedKeys.rsa.RsaPrivateKey } */
26
+ let rsa2
24
27
25
28
before ( async ( ) => {
26
29
rsa = await crypto . keys . generateKeyPair ( 'RSA' , 2048 )
30
+ rsa2 = await crypto . keys . generateKeyPair ( 'RSA' , 2048 )
31
+
32
+ const peerId = await PeerId . createFromPubKey ( rsa . public . bytes )
27
33
28
34
ipfsId = {
29
- id : 'QmQ73f8hbM4hKwRYBqeUsPtiwfE2x6WPv9WnzaYt4nYcXf' ,
30
- publicKey : 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUOR0AJ2/yO0S/JIkKmYV/QdHzQXi1nrTCCXtEbUDVW5mXZfNf9bKeNDfW3UIIOwVzV6/sRhJqq/8sQAhmzURj1q2onCKgSLzjdePSLtykolQeQGSD+JO7rcxOLx+sTdIyJiclP/tkK2gfo2nrI6pjFTKNzR8VSoJx7gfiqY1N9LBgDsD4WjaOM2pBgzgVUlXpk27Aqvcd+htSWi6JuIZaBhPY/IzEvXwntGH9k7F8VkT6nUBilhqFFSWnz8cNKToCHjyhoozKfqN89S7EGMiNvG4cX4Dc/nVXlZRTAi4PNNewutimujROy2/tNEquC2uAlcAzhRAcLL/ujhEjJYP1AgMBAAE='
35
+ id : peerId . toB58String ( ) ,
36
+ publicKey : base64urlpad . encode ( rsa . public . bytes )
31
37
}
32
38
} )
33
39
@@ -43,6 +49,8 @@ describe('ipns', function () {
43
49
expect ( entry ) . to . have . property ( 'validity' )
44
50
expect ( entry ) . to . have . property ( 'signature' )
45
51
expect ( entry ) . to . have . property ( 'validityType' )
52
+ expect ( entry ) . to . have . property ( 'signatureV2' )
53
+ expect ( entry ) . to . have . property ( 'data' )
46
54
} )
47
55
48
56
it ( 'should be able to create a record with a fixed expiration' , async ( ) => {
@@ -121,6 +129,19 @@ describe('ipns', function () {
121
129
expect ( entryDataCreated . validityType ) . to . equal ( unmarshalledData . validityType )
122
130
expect ( entryDataCreated . signature ) . to . equalBytes ( unmarshalledData . signature )
123
131
expect ( entryDataCreated . sequence ) . to . equal ( unmarshalledData . sequence )
132
+ expect ( entryDataCreated . ttl ) . to . equal ( unmarshalledData . ttl )
133
+
134
+ if ( ! unmarshalledData . signatureV2 ) {
135
+ throw new Error ( 'No v2 sig found' )
136
+ }
137
+
138
+ expect ( entryDataCreated . signatureV2 ) . to . equalBytes ( unmarshalledData . signatureV2 )
139
+
140
+ if ( ! unmarshalledData . data ) {
141
+ throw new Error ( 'No v2 data found' )
142
+ }
143
+
144
+ expect ( entryDataCreated . data ) . to . equalBytes ( unmarshalledData . data )
124
145
125
146
return ipns . validate ( rsa . public , unmarshalledData )
126
147
} )
@@ -206,13 +227,13 @@ describe('ipns', function () {
206
227
expect . fail ( 'Expected ERR_UNDEFINED_PARAMETER' )
207
228
} )
208
229
209
- it ( 'should be able to export a previously embed public key from an ipns record' , async ( ) => {
230
+ it ( 'should be able to export a previously embedded public key from an ipns record' , async ( ) => {
210
231
const sequence = 0
211
232
const validity = 1000000
212
233
213
234
const entry = await ipns . create ( rsa , cid , sequence , validity )
214
235
await ipns . embedPublicKey ( rsa . public , entry )
215
- const publicKey = ipns . extractPublicKey ( PeerId . createFromB58String ( ipfsId . id ) , entry )
236
+ const publicKey = await ipns . extractPublicKey ( PeerId . createFromB58String ( ipfsId . id ) , entry )
216
237
expect ( publicKey . bytes ) . to . equalBytes ( rsa . public . bytes )
217
238
} )
218
239
@@ -245,22 +266,63 @@ describe('ipns', function () {
245
266
const keyBytes = base58btc . decode ( `z${ ipfsId . id } ` )
246
267
const key = uint8ArrayConcat ( [ uint8ArrayFromString ( '/ipns/' ) , keyBytes ] )
247
268
248
- try {
249
- await ipns . validator . validate ( marshalledData , key )
250
- } catch ( err ) {
251
- expect ( err ) . to . exist ( )
252
- expect ( err ) . to . include ( {
253
- code : ERRORS . ERR_SIGNATURE_VERIFICATION
254
- } )
255
- }
269
+ await expect ( ipns . validator . validate ( marshalledData , key ) )
270
+ . to . eventually . be . rejected ( ) . with . property ( 'code' , ERRORS . ERR_SIGNATURE_VERIFICATION )
256
271
} )
257
272
258
- it ( 'should use validator.select to select the record with the highest sequence number ' , async ( ) => {
273
+ it ( 'should use validator.validate to verify that a record is not valid when it is passed with the wrong IPNS key ' , async ( ) => {
259
274
const sequence = 0
260
275
const validity = 1000000
261
276
262
277
const entry = await ipns . create ( rsa , cid , sequence , validity )
263
- const newEntry = await ipns . create ( rsa , cid , ( sequence + 1 ) , validity )
278
+ await ipns . embedPublicKey ( rsa . public , entry )
279
+ const marshalledData = ipns . marshal ( entry )
280
+
281
+ const keyBytes = ( await PeerId . createFromPrivKey ( rsa2 . bytes ) ) . toBytes ( )
282
+ const key = uint8ArrayConcat ( [ uint8ArrayFromString ( '/ipns/' ) , keyBytes ] )
283
+
284
+ await expect ( ipns . validator . validate ( marshalledData , key ) )
285
+ . to . eventually . be . rejected ( ) . with . property ( 'code' , ERRORS . ERR_INVALID_EMBEDDED_KEY )
286
+ } )
287
+
288
+ it ( 'should use validator.validate to verify that a record is not valid when the wrong key is embedded' , async ( ) => {
289
+ const sequence = 0
290
+ const validity = 1000000
291
+
292
+ const entry = await ipns . create ( rsa , cid , sequence , validity )
293
+ await ipns . embedPublicKey ( rsa2 . public , entry )
294
+ const marshalledData = ipns . marshal ( entry )
295
+
296
+ const keyBytes = ( await PeerId . createFromPrivKey ( rsa . bytes ) ) . toBytes ( )
297
+ const key = uint8ArrayConcat ( [ uint8ArrayFromString ( '/ipns/' ) , keyBytes ] )
298
+
299
+ await expect ( ipns . validator . validate ( marshalledData , key ) )
300
+ . to . eventually . be . rejected ( ) . with . property ( 'code' , ERRORS . ERR_INVALID_EMBEDDED_KEY )
301
+ } )
302
+
303
+ it ( 'should use validator.select to select the record with the highest sequence number' , async ( ) => {
304
+ const sequence = 0
305
+ const lifetime = 1000000
306
+
307
+ const entry = await ipns . create ( rsa , cid , sequence , lifetime )
308
+ const newEntry = await ipns . create ( rsa , cid , ( sequence + 1 ) , lifetime )
309
+
310
+ const marshalledData = ipns . marshal ( entry )
311
+ const marshalledNewData = ipns . marshal ( newEntry )
312
+
313
+ let valid = ipns . validator . select ( marshalledNewData , marshalledData )
314
+ expect ( valid ) . to . equal ( 0 ) // new data is the selected one
315
+
316
+ valid = ipns . validator . select ( marshalledData , marshalledNewData )
317
+ expect ( valid ) . to . equal ( 1 ) // new data is the selected one
318
+ } )
319
+
320
+ it ( 'should use validator.select to select the record with the longest validity' , async ( ) => {
321
+ const sequence = 0
322
+ const lifetime = 1000000
323
+
324
+ const entry = await ipns . create ( rsa , cid , sequence , lifetime )
325
+ const newEntry = await ipns . create ( rsa , cid , sequence , ( lifetime + 1 ) )
264
326
265
327
const marshalledData = ipns . marshal ( entry )
266
328
const marshalledNewData = ipns . marshal ( newEntry )
@@ -271,4 +333,23 @@ describe('ipns', function () {
271
333
valid = ipns . validator . select ( marshalledData , marshalledNewData )
272
334
expect ( valid ) . to . equal ( 1 ) // new data is the selected one
273
335
} )
336
+
337
+ it ( 'should use validator.select to select an older record with a v2 sig when the newer record only uses v1' , async ( ) => {
338
+ const sequence = 0
339
+ const lifetime = 1000000
340
+
341
+ const entry = await ipns . create ( rsa , cid , sequence , lifetime )
342
+
343
+ const newEntry = await ipns . create ( rsa , cid , sequence + 1 , lifetime )
344
+ delete newEntry . signatureV2
345
+
346
+ const marshalledData = ipns . marshal ( entry )
347
+ const marshalledNewData = ipns . marshal ( newEntry )
348
+
349
+ let valid = ipns . validator . select ( marshalledNewData , marshalledData )
350
+ expect ( valid ) . to . equal ( 1 ) // old data is the selected one
351
+
352
+ valid = ipns . validator . select ( marshalledData , marshalledNewData )
353
+ expect ( valid ) . to . equal ( 0 ) // old data is the selected one
354
+ } )
274
355
} )
0 commit comments