mirror of https://github.com/waku-org/js-noise.git
refactor: SHA256 as parameter
This commit is contained in:
parent
31510dac38
commit
5d54dc28be
|
@ -1,6 +1,7 @@
|
|||
import { ChaCha20Poly1305, TAG_LENGTH } from "@stablelib/chacha20poly1305";
|
||||
import { Hash } from "@stablelib/hash";
|
||||
import { HKDF as hkdf } from "@stablelib/hkdf";
|
||||
import { hash, SHA256 } from "@stablelib/sha256";
|
||||
import { hash } from "@stablelib/sha256";
|
||||
import * as x25519 from "@stablelib/x25519";
|
||||
import { concat as uint8ArrayConcat } from "uint8arrays/concat";
|
||||
|
||||
|
@ -43,9 +44,15 @@ export function intoCurve25519Key(s: Uint8Array): bytes32 {
|
|||
* @param numKeys number of keys to generate
|
||||
* @returns array of `numValues` length containing Uint8Array keys of a given byte `length`
|
||||
*/
|
||||
export function HKDF(ck: bytes32, ikm: Uint8Array, length: number, numKeys: number): Array<Uint8Array> {
|
||||
export function HKDF(
|
||||
hash: new () => Hash,
|
||||
ck: bytes32,
|
||||
ikm: Uint8Array,
|
||||
length: number,
|
||||
numKeys: number
|
||||
): Array<Uint8Array> {
|
||||
const numBytes = length * numKeys;
|
||||
const okm = new hkdf(SHA256, ikm, ck).expand(numBytes);
|
||||
const okm = new hkdf(hash, ikm, ck).expand(numBytes);
|
||||
const result = [];
|
||||
for (let i = 0; i < numBytes; i += length) {
|
||||
const k = okm.subarray(i, i + length);
|
||||
|
|
|
@ -173,7 +173,7 @@ export class Handshake {
|
|||
|
||||
// Generates an 8 decimal digits authorization code using HKDF and the handshake state
|
||||
genAuthcode(): string {
|
||||
const [output0] = HKDF(this.hs.ss.h, new Uint8Array(), 8, 1);
|
||||
const [output0] = HKDF(this.hs.handshakePattern.hash, this.hs.ss.h, new Uint8Array(), 8, 1);
|
||||
const bn = new BN(output0);
|
||||
const code = bn.mod(new BN(100_000_000)).toString().padStart(8, "0");
|
||||
return code.toString();
|
||||
|
|
|
@ -31,19 +31,14 @@ export class HandshakeState {
|
|||
re?: bytes32;
|
||||
ss: SymmetricState;
|
||||
initiator: boolean;
|
||||
handshakePattern: HandshakePattern;
|
||||
msgPatternIdx: number;
|
||||
psk: Uint8Array;
|
||||
|
||||
constructor(hsPattern: HandshakePattern, psk: Uint8Array) {
|
||||
constructor(public readonly handshakePattern: HandshakePattern, public psk: Uint8Array) {
|
||||
// By default the Handshake State initiator flag is set to false
|
||||
// Will be set to true when the user associated to the handshake state starts an handshake
|
||||
this.initiator = false;
|
||||
|
||||
this.handshakePattern = hsPattern;
|
||||
this.psk = psk;
|
||||
|
||||
this.ss = new SymmetricState(hsPattern);
|
||||
this.ss = new SymmetricState(handshakePattern);
|
||||
|
||||
this.msgPatternIdx = 0;
|
||||
}
|
||||
|
@ -101,14 +96,14 @@ export class HandshakeState {
|
|||
}
|
||||
|
||||
genMessageNametagSecrets(): { nms1: Uint8Array; nms2: Uint8Array } {
|
||||
const [nms1, nms2] = HKDF(this.ss.h, new Uint8Array(), 2, 32);
|
||||
const [nms1, nms2] = HKDF(this.handshakePattern.hash, this.ss.h, new Uint8Array(), 2, 32);
|
||||
return { nms1, nms2 };
|
||||
}
|
||||
|
||||
// Uses the cryptographic information stored in the input handshake state to generate a random message nametag
|
||||
// In current implementation the messageNametag = HKDF(handshake hash value), but other derivation mechanisms can be implemented
|
||||
toMessageNametag(): MessageNametag {
|
||||
const [output] = HKDF(this.ss.h, new Uint8Array(), 32, 1);
|
||||
const [output] = HKDF(this.handshakePattern.hash, this.ss.h, new Uint8Array(), 32, 1);
|
||||
return output.subarray(0, MessageNametagLength);
|
||||
}
|
||||
|
||||
|
|
15
src/noise.ts
15
src/noise.ts
|
@ -216,11 +216,10 @@ export class SymmetricState {
|
|||
h: bytes32; // handshake hash
|
||||
private ck: bytes32; // chaining key
|
||||
|
||||
constructor(private readonly hsPattern: HandshakePattern) {
|
||||
this.h = hashProtocol(hsPattern.name);
|
||||
constructor(private readonly handshakePattern: HandshakePattern) {
|
||||
this.h = hashProtocol(handshakePattern.name);
|
||||
this.ck = this.h;
|
||||
this.cs = new CipherState();
|
||||
this.hsPattern = hsPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -233,7 +232,7 @@ export class SymmetricState {
|
|||
this.cs.equals(other.cs) &&
|
||||
uint8ArrayEquals(this.ck, other.ck) &&
|
||||
uint8ArrayEquals(this.h, other.h) &&
|
||||
this.hsPattern.equals(other.hsPattern)
|
||||
this.handshakePattern.equals(other.handshakePattern)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -242,7 +241,7 @@ export class SymmetricState {
|
|||
* @returns a copy of the SymmetricState
|
||||
*/
|
||||
clone(): SymmetricState {
|
||||
const ss = new SymmetricState(this.hsPattern);
|
||||
const ss = new SymmetricState(this.handshakePattern);
|
||||
ss.cs = this.cs.clone();
|
||||
ss.ck = new Uint8Array(this.ck);
|
||||
ss.h = new Uint8Array(this.h);
|
||||
|
@ -256,7 +255,7 @@ export class SymmetricState {
|
|||
*/
|
||||
mixKey(inputKeyMaterial: Uint8Array): void {
|
||||
// We derive two keys using HKDF
|
||||
const [ck, tempK] = HKDF(this.ck, inputKeyMaterial, 32, 2);
|
||||
const [ck, tempK] = HKDF(this.handshakePattern.hash, this.ck, inputKeyMaterial, 32, 2);
|
||||
// We update ck and the Cipher state's key k using the output of HDKF
|
||||
this.cs = new CipherState(tempK);
|
||||
this.ck = ck;
|
||||
|
@ -281,7 +280,7 @@ export class SymmetricState {
|
|||
*/
|
||||
mixKeyAndHash(inputKeyMaterial: Uint8Array): void {
|
||||
// Derives 3 keys using HKDF, the chaining key and the input key material
|
||||
const [tmpKey0, tmpKey1, tmpKey2] = HKDF(this.ck, inputKeyMaterial, 32, 3);
|
||||
const [tmpKey0, tmpKey1, tmpKey2] = HKDF(this.handshakePattern.hash, this.ck, inputKeyMaterial, 32, 3);
|
||||
// Sets the chaining key
|
||||
this.ck = tmpKey0;
|
||||
// Updates the handshake hash value
|
||||
|
@ -334,7 +333,7 @@ export class SymmetricState {
|
|||
*/
|
||||
split(): { cs1: CipherState; cs2: CipherState } {
|
||||
// Derives 2 keys using HKDF and the chaining key
|
||||
const [tmpKey1, tmpKey2] = HKDF(this.ck, new Uint8Array(0), 32, 2);
|
||||
const [tmpKey1, tmpKey2] = HKDF(this.handshakePattern.hash, this.ck, new Uint8Array(0), 32, 2);
|
||||
// Returns a tuple of two Cipher States initialized with the derived keys
|
||||
return {
|
||||
cs1: new CipherState(tmpKey1),
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import { Hash } from "@stablelib/hash";
|
||||
import { SHA256 } from "@stablelib/sha256";
|
||||
|
||||
/**
|
||||
* The Noise tokens appearing in Noise (pre)message patterns
|
||||
* as in http://www.noiseprotocol.org/noise.html#handshake-pattern-basics
|
||||
|
@ -70,6 +73,7 @@ export class MessagePattern {
|
|||
export class HandshakePattern {
|
||||
constructor(
|
||||
public readonly name: string,
|
||||
public readonly hash: new () => Hash,
|
||||
public readonly preMessagePatterns: Array<PreMessagePattern>,
|
||||
public readonly messagePatterns: Array<MessagePattern>
|
||||
) {}
|
||||
|
@ -100,6 +104,7 @@ export class HandshakePattern {
|
|||
export const NoiseHandshakePatterns = {
|
||||
K1K1: new HandshakePattern(
|
||||
"Noise_K1K1_25519_ChaChaPoly_SHA256",
|
||||
SHA256,
|
||||
[
|
||||
new PreMessagePattern(MessageDirection.r, [NoiseTokens.s]),
|
||||
new PreMessagePattern(MessageDirection.l, [NoiseTokens.s]),
|
||||
|
@ -112,6 +117,7 @@ export const NoiseHandshakePatterns = {
|
|||
),
|
||||
XK1: new HandshakePattern(
|
||||
"Noise_XK1_25519_ChaChaPoly_SHA256",
|
||||
SHA256,
|
||||
[new PreMessagePattern(MessageDirection.l, [NoiseTokens.s])],
|
||||
[
|
||||
new MessagePattern(MessageDirection.r, [NoiseTokens.e]),
|
||||
|
@ -121,6 +127,7 @@ export const NoiseHandshakePatterns = {
|
|||
),
|
||||
XX: new HandshakePattern(
|
||||
"Noise_XX_25519_ChaChaPoly_SHA256",
|
||||
SHA256,
|
||||
[],
|
||||
[
|
||||
new MessagePattern(MessageDirection.r, [NoiseTokens.e]),
|
||||
|
@ -130,6 +137,7 @@ export const NoiseHandshakePatterns = {
|
|||
),
|
||||
XXpsk0: new HandshakePattern(
|
||||
"Noise_XXpsk0_25519_ChaChaPoly_SHA256",
|
||||
SHA256,
|
||||
[],
|
||||
[
|
||||
new MessagePattern(MessageDirection.r, [NoiseTokens.psk, NoiseTokens.e]),
|
||||
|
@ -139,6 +147,7 @@ export const NoiseHandshakePatterns = {
|
|||
),
|
||||
WakuPairing: new HandshakePattern(
|
||||
"Noise_WakuPairing_25519_ChaChaPoly_SHA256",
|
||||
SHA256,
|
||||
[new PreMessagePattern(MessageDirection.l, [NoiseTokens.e])],
|
||||
[
|
||||
new MessagePattern(MessageDirection.r, [NoiseTokens.e, NoiseTokens.ee]),
|
||||
|
|
Loading…
Reference in New Issue