From 7b9118e15b871edc5d74f7f475e024e2267a057e Mon Sep 17 00:00:00 2001 From: Belma Gutlic Date: Wed, 25 Dec 2019 11:11:07 +0100 Subject: [PATCH] Move remaining functions from XX --- src/handshakes/abstract-handshake.ts | 99 ++++++++++++++++++++++++++++ src/handshakes/xx.ts | 99 ---------------------------- test/handshakes/xx.test.ts | 4 +- 3 files changed, 101 insertions(+), 101 deletions(-) diff --git a/src/handshakes/abstract-handshake.ts b/src/handshakes/abstract-handshake.ts index e34a901..8b99f74 100644 --- a/src/handshakes/abstract-handshake.ts +++ b/src/handshakes/abstract-handshake.ts @@ -8,6 +8,39 @@ import {getHkdf} from "../utils"; export class AbstractHandshake { protected minNonce = 0; + public encryptWithAd(cs: CipherState, ad: bytes, plaintext: bytes): bytes { + const e = this.encrypt(cs.k, cs.n, ad, plaintext); + this.setNonce(cs, this.incrementNonce(cs.n)); + + return e; + } + + public decryptWithAd(cs: CipherState, ad: bytes, ciphertext: bytes): bytes { + const plaintext = this.decrypt(cs.k, cs.n, ad, ciphertext); + this.setNonce(cs, this.incrementNonce(cs.n)); + + return plaintext; + } + + + // Cipher state related + protected hasKey(cs: CipherState): boolean { + return !this.isEmptyKey(cs.k); + } + + protected setNonce(cs: CipherState, nonce: uint32): void { + cs.n = nonce; + } + + protected createEmptyKey(): bytes32 { + return Buffer.alloc(32); + } + + protected isEmptyKey(k: bytes32): boolean { + const emptyKey = this.createEmptyKey(); + return emptyKey.equals(k); + } + protected incrementNonce(n: uint32): uint32 { return n + 1; } @@ -31,6 +64,41 @@ export class AbstractHandshake { return plaintext; } + protected encryptAndHash(ss: SymmetricState, plaintext: bytes): bytes { + let ciphertext; + if (this.hasKey(ss.cs)) { + ciphertext = this.encryptWithAd(ss.cs, ss.h, plaintext); + } else { + ciphertext = plaintext; + } + + this.mixHash(ss, ciphertext); + return ciphertext; + } + + protected decrypt(k: bytes32, n: uint32, ad: bytes, ciphertext: bytes): bytes { + const nonce = this.nonceToBytes(n); + const ctx = new AEAD(); + + ctx.init(k, nonce); + ctx.aad(ad); + ctx.decrypt(ciphertext); + + // Decryption is done on the sent reference + return ciphertext; + } + + protected decryptAndHash(ss: SymmetricState, ciphertext: bytes): bytes { + let plaintext; + if (this.hasKey(ss.cs)) { + plaintext = this.decryptWithAd(ss.cs, ss.h, ciphertext); + } else { + plaintext = ciphertext; + } + + this.mixHash(ss, ciphertext); + return plaintext; + } protected dh(privateKey: bytes32, publicKey: bytes32): bytes32 { const derived = x25519.derive(publicKey, privateKey); @@ -57,4 +125,35 @@ export class AbstractHandshake { const n = this.minNonce; return { k, n }; } + + // Symmetric state related + + protected initializeSymmetric(protocolName: string): SymmetricState { + const protocolNameBytes: bytes = Buffer.from(protocolName, 'utf-8'); + const h = this.hashProtocolName(protocolNameBytes); + + const ck = h; + const key = this.createEmptyKey(); + const cs: CipherState = this.initializeKey(key); + + return { cs, ck, h }; + } + + protected hashProtocolName(protocolName: bytes): bytes32 { + if (protocolName.length <= 32) { + const h = Buffer.alloc(32); + protocolName.copy(h); + return h; + } else { + return this.getHash(protocolName, Buffer.alloc(0)); + } + } + + protected split (ss: SymmetricState) { + const [ tempk1, tempk2 ] = getHkdf(ss.ck, Buffer.alloc(0)); + const cs1 = this.initializeKey(tempk1); + const cs2 = this.initializeKey(tempk2); + + return { cs1, cs2 }; + } } diff --git a/src/handshakes/xx.ts b/src/handshakes/xx.ts index 3273ed6..6e95ccc 100644 --- a/src/handshakes/xx.ts +++ b/src/handshakes/xx.ts @@ -10,10 +10,6 @@ import {AbstractHandshake} from "./abstract-handshake"; export class XXHandshake extends AbstractHandshake { - private createEmptyKey(): bytes32 { - return Buffer.alloc(32); - } - private initializeInitiator(prologue: bytes32, s: KeyPair, rs: bytes32, psk: bytes32): HandshakeState { const name = "Noise_XX_25519_ChaChaPoly_SHA256"; const ss = this.initializeSymmetric(name); @@ -32,101 +28,6 @@ export class XXHandshake extends AbstractHandshake { return { ss, s, rs, psk, re }; } - private decrypt(k: bytes32, n: uint32, ad: bytes, ciphertext: bytes): bytes { - const nonce = this.nonceToBytes(n); - const ctx = new AEAD(); - - ctx.init(k, nonce); - ctx.aad(ad); - ctx.decrypt(ciphertext); - - // Decryption is done on the sent reference - return ciphertext; - } - - private isEmptyKey(k: bytes32): boolean { - const emptyKey = this.createEmptyKey(); - return emptyKey.equals(k); - } - - // Cipher state related - private hasKey(cs: CipherState): boolean { - return !this.isEmptyKey(cs.k); - } - - private setNonce(cs: CipherState, nonce: uint32): void { - cs.n = nonce; - } - - public encryptWithAd(cs: CipherState, ad: bytes, plaintext: bytes): bytes { - const e = this.encrypt(cs.k, cs.n, ad, plaintext); - this.setNonce(cs, this.incrementNonce(cs.n)); - - return e; - } - - public decryptWithAd(cs: CipherState, ad: bytes, ciphertext: bytes): bytes { - const plaintext = this.decrypt(cs.k, cs.n, ad, ciphertext); - this.setNonce(cs, this.incrementNonce(cs.n)); - - return plaintext; - } - - // Symmetric state related - - private initializeSymmetric(protocolName: string): SymmetricState { - const protocolNameBytes: bytes = Buffer.from(protocolName, 'utf-8'); - const h = this.hashProtocolName(protocolNameBytes); - - const ck = h; - const key = this.createEmptyKey(); - const cs: CipherState = this.initializeKey(key); - - return { cs, ck, h }; - } - - private hashProtocolName(protocolName: bytes): bytes32 { - if (protocolName.length <= 32) { - const h = Buffer.alloc(32); - protocolName.copy(h); - return h; - } else { - return this.getHash(protocolName, Buffer.alloc(0)); - } - } - - private encryptAndHash(ss: SymmetricState, plaintext: bytes): bytes { - let ciphertext; - if (this.hasKey(ss.cs)) { - ciphertext = this.encryptWithAd(ss.cs, ss.h, plaintext); - } else { - ciphertext = plaintext; - } - - this.mixHash(ss, ciphertext); - return ciphertext; - } - - private decryptAndHash(ss: SymmetricState, ciphertext: bytes): bytes { - let plaintext; - if (this.hasKey(ss.cs)) { - plaintext = this.decryptWithAd(ss.cs, ss.h, ciphertext); - } else { - plaintext = ciphertext; - } - - this.mixHash(ss, ciphertext); - return plaintext; - } - - private split (ss: SymmetricState) { - const [ tempk1, tempk2 ] = getHkdf(ss.ck, Buffer.alloc(0)); - const cs1 = this.initializeKey(tempk1); - const cs2 = this.initializeKey(tempk2); - - return { cs1, cs2 }; - } - private writeMessageA(hs: HandshakeState, payload: bytes): MessageBuffer { const ns = Buffer.alloc(0); hs.e = generateKeypair(); diff --git a/test/handshakes/xx.test.ts b/test/handshakes/xx.test.ts index 4bc7e1a..b6d93f4 100644 --- a/test/handshakes/xx.test.ts +++ b/test/handshakes/xx.test.ts @@ -4,7 +4,7 @@ import { Buffer } from 'buffer'; import { XXHandshake } from "../../src/handshakes/xx"; import { KeyPair } from "../../src/@types/libp2p"; import { generateEd25519Keys } from "../utils"; -import {createHandshakePayload, generateKeypair, getHandshakePayload} from "../../src/utils"; +import {createHandshakePayload, generateKeypair, getHandshakePayload, getHkdf} from "../../src/utils"; describe("Index", () => { const prologue = Buffer.from("/noise", "utf-8"); @@ -29,7 +29,7 @@ describe("Index", () => { const ck = Buffer.alloc(32); ckBytes.copy(ck); - const [k1, k2, k3] = xx.getHkdf(ck, ikm); + 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');