mirror of
https://github.com/fluencelabs/js-libp2p-noise
synced 2025-04-25 14:32:18 +00:00
Move remaining functions from XX
This commit is contained in:
parent
0290df8685
commit
7b9118e15b
@ -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 };
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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');
|
||||
|
Loading…
x
Reference in New Issue
Block a user