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