144 lines
5.1 KiB
TypeScript
Raw Normal View History

2020-06-19 12:49:40 +02:00
import { expect, assert } from 'chai'
import { Buffer } from 'buffer'
2020-06-19 12:49:40 +02:00
import { XX } from '../../src/handshakes/xx'
import { KeyPair } from '../../src/@types/libp2p'
import { generateEd25519Keys } from '../utils'
import { createHandshakePayload, generateKeypair, getHandshakePayload, getHkdf } from '../../src/utils'
2020-06-19 12:49:40 +02:00
describe('XX Handshake', () => {
const prologue = Buffer.alloc(0)
2020-06-19 12:49:40 +02:00
it('Test creating new XX session', async () => {
2019-11-28 17:32:46 +01:00
try {
2020-06-19 12:49:40 +02:00
const xx = new XX()
2019-11-04 21:34:12 +01:00
2020-06-19 12:49:40 +02:00
const kpInitiator: KeyPair = await generateKeypair()
2020-06-19 13:06:31 +02:00
await generateKeypair()
2019-11-04 21:34:12 +01:00
2020-06-19 13:06:31 +02:00
await xx.initSession(true, prologue, kpInitiator)
2019-11-28 17:32:46 +01:00
} catch (e) {
2020-06-19 12:49:40 +02:00
assert(false, e.message)
2019-11-28 17:32:46 +01:00
}
2020-06-19 12:49:40 +02:00
})
2019-11-05 13:25:03 +01:00
2020-06-19 13:06:31 +02:00
it('Test get HKDF', () => {
2020-06-19 12:49:40 +02:00
const ckBytes = Buffer.from('4e6f6973655f58585f32353531395f58436861436861506f6c795f53484132353600000000000000000000000000000000000000000000000000000000000000', 'hex')
const ikm = Buffer.from('a3eae50ea37a47e8a7aa0c7cd8e16528670536dcd538cebfd724fb68ce44f1910ad898860666227d4e8dd50d22a9a64d1c0a6f47ace092510161e9e442953da3', 'hex')
const ck = Buffer.alloc(32)
ckBytes.copy(ck)
2019-11-05 13:25:03 +01:00
2020-06-19 12:49:40 +02:00
const [k1, k2, k3] = getHkdf(ck, ikm)
expect(k1.toString('hex')).to.equal('cc5659adff12714982f806e2477a8d5ddd071def4c29bb38777b7e37046f6914')
expect(k2.toString('hex')).to.equal('a16ada915e551ab623f38be674bb4ef15d428ae9d80688899c9ef9b62ef208fa')
expect(k3.toString('hex')).to.equal('ff67bf9727e31b06efc203907e6786667d2c7a74ac412b4d31a80ba3fd766f68')
})
2020-06-19 12:49:40 +02:00
async function doHandshake (xx) {
const kpInit = await generateKeypair()
const kpResp = await generateKeypair()
// initiator setup
2020-06-19 12:49:40 +02:00
const libp2pInitKeys = await generateEd25519Keys()
const initSignedPayload = await libp2pInitKeys.sign(getHandshakePayload(kpInit.publicKey))
// responder setup
2020-06-19 12:49:40 +02:00
const libp2pRespKeys = await generateEd25519Keys()
const respSignedPayload = await libp2pRespKeys.sign(getHandshakePayload(kpResp.publicKey))
// initiator: new XX noise session
2020-06-19 12:49:40 +02:00
const nsInit = xx.initSession(true, prologue, kpInit)
// responder: new XX noise session
2020-06-19 12:49:40 +02:00
const nsResp = xx.initSession(false, prologue, kpResp)
2019-11-06 15:16:13 +01:00
/* STAGE 0 */
// initiator creates payload
2020-06-19 13:06:31 +02:00
libp2pInitKeys.marshal().slice(0, 32)
2020-06-19 12:49:40 +02:00
const libp2pInitPubKey = libp2pInitKeys.marshal().slice(32, 64)
2019-12-03 13:52:44 +01:00
2020-06-19 12:49:40 +02:00
const payloadInitEnc = await createHandshakePayload(libp2pInitPubKey, initSignedPayload)
// initiator sends message
2020-06-19 12:49:40 +02:00
const message = Buffer.concat([Buffer.alloc(0), payloadInitEnc])
const messageBuffer = xx.sendMessage(nsInit, message)
2020-06-19 12:49:40 +02:00
expect(messageBuffer.ne.length).not.equal(0)
2019-11-06 15:16:13 +01:00
// responder receives message
2020-06-19 12:49:40 +02:00
xx.recvMessage(nsResp, messageBuffer)
2019-11-06 15:16:13 +01:00
/* STAGE 1 */
// responder creates payload
2020-06-19 13:06:31 +02:00
libp2pRespKeys.marshal().slice(0, 32)
2020-06-19 12:49:40 +02:00
const libp2pRespPubKey = libp2pRespKeys.marshal().slice(32, 64)
const payloadRespEnc = await createHandshakePayload(libp2pRespPubKey, respSignedPayload)
2019-11-06 15:16:13 +01:00
2020-06-19 12:49:40 +02:00
const message1 = Buffer.concat([message, payloadRespEnc])
const messageBuffer2 = xx.sendMessage(nsResp, message1)
2019-11-06 15:16:13 +01:00
2020-06-19 12:49:40 +02:00
expect(messageBuffer2.ne.length).not.equal(0)
expect(messageBuffer2.ns.length).not.equal(0)
2019-11-06 15:45:28 +01:00
// initiator receive payload
2020-06-19 12:49:40 +02:00
xx.recvMessage(nsInit, messageBuffer2)
2019-11-06 15:49:20 +01:00
/* STAGE 2 */
// initiator send message
2020-06-19 12:49:40 +02:00
const messageBuffer3 = xx.sendMessage(nsInit, Buffer.alloc(0))
2019-11-06 16:09:15 +01:00
2019-11-06 15:49:20 +01:00
// responder receive message
2020-06-19 12:49:40 +02:00
xx.recvMessage(nsResp, messageBuffer3)
2019-11-06 15:49:20 +01:00
2020-06-19 12:49:40 +02:00
assert(nsInit.cs1.k.equals(nsResp.cs1.k))
assert(nsInit.cs2.k.equals(nsResp.cs2.k))
2019-11-06 16:09:15 +01:00
2020-06-19 12:49:40 +02:00
return { nsInit, nsResp }
}
2020-06-19 12:49:40 +02:00
it('Test handshake', async () => {
2019-11-28 17:32:46 +01:00
try {
2020-06-19 12:49:40 +02:00
const xx = new XX()
await doHandshake(xx)
2019-11-28 17:32:46 +01:00
} catch (e) {
2020-06-19 12:49:40 +02:00
assert(false, e.message)
2019-11-28 17:32:46 +01:00
}
2020-06-19 12:49:40 +02:00
})
2019-11-07 10:55:18 +01:00
2020-06-19 12:49:40 +02:00
it('Test symmetric encrypt and decrypt', async () => {
2019-11-28 17:32:46 +01:00
try {
2020-06-19 12:49:40 +02:00
const xx = new XX()
const { nsInit, nsResp } = await doHandshake(xx)
const ad = Buffer.from('authenticated')
const message = Buffer.from('HelloCrypto')
2019-11-28 17:32:46 +01:00
2020-06-19 12:49:40 +02:00
const ciphertext = xx.encryptWithAd(nsInit.cs1, ad, message)
assert(!Buffer.from('HelloCrypto').equals(ciphertext), 'Encrypted message should not be same as plaintext.')
const { plaintext: decrypted, valid } = xx.decryptWithAd(nsResp.cs1, ad, ciphertext)
2019-11-28 17:32:46 +01:00
2020-06-19 12:49:40 +02:00
assert(Buffer.from('HelloCrypto').equals(decrypted), 'Decrypted text not equal to original message.')
assert(valid)
2019-11-28 17:32:46 +01:00
} catch (e) {
2020-06-19 12:49:40 +02:00
assert(false, e.message)
2019-11-28 17:32:46 +01:00
}
2020-06-19 12:49:40 +02:00
})
it('Test multiple messages encryption and decryption', async () => {
const xx = new XX()
const { nsInit, nsResp } = await doHandshake(xx)
const ad = Buffer.from('authenticated')
const message = Buffer.from('ethereum1')
const encrypted = xx.encryptWithAd(nsInit.cs1, ad, message)
const { plaintext: decrypted } = xx.decryptWithAd(nsResp.cs1, ad, encrypted)
assert.equal('ethereum1', decrypted.toString('utf8'), 'Decrypted text not equal to original message.')
const message2 = Buffer.from('ethereum2')
const encrypted2 = xx.encryptWithAd(nsInit.cs1, ad, message2)
const { plaintext: decrypted2 } = xx.decryptWithAd(nsResp.cs1, ad, encrypted2)
assert.equal('ethereum2', decrypted2.toString('utf-8'), 'Decrypted text not equal to original message.')
})
})