mirror of
https://github.com/logos-messaging/js-noise.git
synced 2026-01-04 06:33:08 +00:00
refactor: make nametag buffers optional
This commit is contained in:
parent
aafdf61572
commit
eeafc497e4
@ -96,7 +96,7 @@ export class NoiseSecureTransferEncoder implements Encoder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const preparedPayload = this.hsResult.writeMessage(message.payload, this.hsResult.nametagsOutbound);
|
const preparedPayload = this.hsResult.writeMessage(message.payload);
|
||||||
|
|
||||||
const payload = preparedPayload.serialize();
|
const payload = preparedPayload.serialize();
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ export class NoiseSecureTransferDecoder implements Decoder<NoiseSecureMessage> {
|
|||||||
|
|
||||||
const payloadV2 = PayloadV2.deserialize(proto.payload);
|
const payloadV2 = PayloadV2.deserialize(proto.payload);
|
||||||
|
|
||||||
const decryptedPayload = this.hsResult.readMessage(payloadV2, this.hsResult.nametagsInbound);
|
const decryptedPayload = this.hsResult.readMessage(payloadV2);
|
||||||
|
|
||||||
return new NoiseSecureMessage(proto, decryptedPayload);
|
return new NoiseSecureMessage(proto, decryptedPayload);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,10 +24,7 @@ export function intoCurve25519Key(s: Uint8Array): bytes32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getHKDF(ck: bytes32, ikm: Uint8Array): Hkdf {
|
export function getHKDF(ck: bytes32, ikm: Uint8Array): Hkdf {
|
||||||
const hkdf = new HKDF(SHA256, ikm, ck);
|
const okm = getHKDFRaw(ck, ikm, 96);
|
||||||
const okmU8Array = hkdf.expand(96);
|
|
||||||
const okm = okmU8Array;
|
|
||||||
|
|
||||||
const k1 = okm.subarray(0, 32);
|
const k1 = okm.subarray(0, 32);
|
||||||
const k2 = okm.subarray(32, 64);
|
const k2 = okm.subarray(32, 64);
|
||||||
const k3 = okm.subarray(64, 96);
|
const k3 = okm.subarray(64, 96);
|
||||||
|
|||||||
@ -55,11 +55,14 @@ export class HandshakeResult {
|
|||||||
// due to nonce exhaustion, then the application must delete the CipherState and terminate the session.
|
// due to nonce exhaustion, then the application must delete the CipherState and terminate the session.
|
||||||
|
|
||||||
// Writes an encrypted message using the proper Cipher State
|
// Writes an encrypted message using the proper Cipher State
|
||||||
writeMessage(transportMessage: Uint8Array, outboundMessageNametagBuffer: MessageNametagBuffer): PayloadV2 {
|
writeMessage(
|
||||||
|
transportMessage: Uint8Array,
|
||||||
|
outboundMessageNametagBuffer: MessageNametagBuffer | undefined = undefined
|
||||||
|
): PayloadV2 {
|
||||||
const payload2 = new PayloadV2();
|
const payload2 = new PayloadV2();
|
||||||
|
|
||||||
// We set the message nametag using the input buffer
|
// We set the message nametag using the input buffer
|
||||||
payload2.messageNametag = outboundMessageNametagBuffer.pop();
|
payload2.messageNametag = (outboundMessageNametagBuffer ?? this.nametagsOutbound).pop();
|
||||||
|
|
||||||
// According to 35/WAKU2-NOISE RFC, no Handshake protocol information is sent when exchanging messages
|
// According to 35/WAKU2-NOISE RFC, no Handshake protocol information is sent when exchanging messages
|
||||||
// This correspond to setting protocol-id to 0
|
// This correspond to setting protocol-id to 0
|
||||||
@ -74,13 +77,16 @@ export class HandshakeResult {
|
|||||||
|
|
||||||
// Reads an encrypted message using the proper Cipher State
|
// Reads an encrypted message using the proper Cipher State
|
||||||
// Decryption is attempted only if the input PayloadV2 has a messageNametag equal to the one expected
|
// Decryption is attempted only if the input PayloadV2 has a messageNametag equal to the one expected
|
||||||
readMessage(readPayload2: PayloadV2, inboundMessageNametagBuffer: MessageNametagBuffer): Uint8Array {
|
readMessage(
|
||||||
|
readPayload2: PayloadV2,
|
||||||
|
inboundMessageNametagBuffer: MessageNametagBuffer | undefined = undefined
|
||||||
|
): Uint8Array {
|
||||||
// The output decrypted message
|
// The output decrypted message
|
||||||
let message = new Uint8Array();
|
let message = new Uint8Array();
|
||||||
|
|
||||||
// If the message nametag does not correspond to the nametag expected in the inbound message nametag buffer
|
// If the message nametag does not correspond to the nametag expected in the inbound message nametag buffer
|
||||||
// an error is raised (to be handled externally, i.e. re-request lost messages, discard, etc.)
|
// an error is raised (to be handled externally, i.e. re-request lost messages, discard, etc.)
|
||||||
const nametagIsOk = inboundMessageNametagBuffer.checkNametag(readPayload2.messageNametag);
|
const nametagIsOk = (inboundMessageNametagBuffer ?? this.nametagsInbound).checkNametag(readPayload2.messageNametag);
|
||||||
if (!nametagIsOk) {
|
if (!nametagIsOk) {
|
||||||
throw new Error("nametag is not ok");
|
throw new Error("nametag is not ok");
|
||||||
}
|
}
|
||||||
@ -95,7 +101,7 @@ export class HandshakeResult {
|
|||||||
// We unpad the decrypted message
|
// We unpad the decrypted message
|
||||||
message = pkcs7.unpad(paddedMessage);
|
message = pkcs7.unpad(paddedMessage);
|
||||||
// The message successfully decrypted, we can delete the first element of the inbound Message Nametag Buffer
|
// The message successfully decrypted, we can delete the first element of the inbound Message Nametag Buffer
|
||||||
inboundMessageNametagBuffer.delete(1);
|
this.nametagsInbound.delete(1);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.debug("A read message failed decryption. Returning empty message as plaintext.");
|
console.debug("A read message failed decryption. Returning empty message as plaintext.");
|
||||||
message = new Uint8Array();
|
message = new Uint8Array();
|
||||||
|
|||||||
@ -246,51 +246,40 @@ describe("Waku Noise Sessions", () => {
|
|||||||
expect(uint8ArrayEquals(message, readMessage!.payload)).to.be.true;
|
expect(uint8ArrayEquals(message, readMessage!.payload)).to.be.true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
/*
|
|
||||||
// We test how nametag buffers help in detecting lost messages
|
// We test how nametag buffers help in detecting lost messages
|
||||||
// Alice writes two messages to Bob, but only the second is received
|
// Alice writes two messages to Bob, but only the second is received
|
||||||
|
let message = randomBytes(32, rng);
|
||||||
|
let payload2 = aliceHSResult.writeMessage(message);
|
||||||
|
message = randomBytes(32, rng);
|
||||||
|
payload2 = aliceHSResult.writeMessage(message);
|
||||||
try {
|
try {
|
||||||
const message = randomBytes(32, rng);
|
bobHSResult.readMessage(payload2);
|
||||||
payload2 = aliceHSResult.writeMessage(message, aliceHSResult.nametagsOutbound);
|
expect(false, "should not reach here").to.be.true;
|
||||||
message = randomBytes(32, rng);
|
} catch (err) {
|
||||||
payload2 = aliceHSResult.writeMessage(aliceHSResult.nametagsOutbound);
|
let message;
|
||||||
} catch (NoiseSomeMessagesWereLost) {
|
if (err instanceof Error) message = err.message;
|
||||||
let readMessage = readMessage(
|
else message = String(err);
|
||||||
bobHSResult,
|
expect(message).to.be.equals("nametag is not ok");
|
||||||
payload2,
|
|
||||||
(inboundMessageNametagBuffer = bobHSResult.nametagsInbound)
|
|
||||||
).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We adjust bob nametag buffer for next test (i.e. the missed message is correctly recovered)
|
// We adjust bob nametag buffer for next test (i.e. the missed message is correctly recovered)
|
||||||
bobHSResult.nametagsInbound.delete(2);
|
bobHSResult.nametagsInbound.delete(2);
|
||||||
let message = randomBytes(32, rng);
|
message = randomBytes(32, rng);
|
||||||
payload2 = writeMessage(bobHSResult, message, (outboundMessageNametagBuffer = bobHSResult.nametagsOutbound));
|
payload2 = bobHSResult.writeMessage(message);
|
||||||
readMessage = readMessage(
|
const readMessage = aliceHSResult.readMessage(payload2);
|
||||||
aliceHSResult,
|
expect(uint8ArrayEquals(message, readMessage)).to.be.true;
|
||||||
payload2,
|
|
||||||
(inboundMessageNametagBuffer = aliceHSResult.nametagsInbound)
|
|
||||||
).get();
|
|
||||||
|
|
||||||
expect(uint8ArrayEquals(message, readMessage!.payload)).to.be.true;
|
|
||||||
|
|
||||||
// We test if a missing nametag is correctly detected
|
// We test if a missing nametag is correctly detected
|
||||||
|
message = randomBytes(32, rng);
|
||||||
|
payload2 = aliceHSResult.writeMessage(message);
|
||||||
|
bobHSResult.nametagsInbound.delete(1);
|
||||||
try {
|
try {
|
||||||
const message = randomBytes(32, rng);
|
bobHSResult.readMessage(payload2);
|
||||||
const payload2 = aliceHSResult.writeMessage(message, aliceHSResult.nametagsOutbound);
|
} catch (err) {
|
||||||
bobHSResult.nametagsInbound.delete(1);
|
let message;
|
||||||
} catch (NoiseMessageNametagError) {
|
if (err instanceof Error) message = err.message;
|
||||||
let readMessage = readMessage(
|
else message = String(err);
|
||||||
bobHSResult,
|
expect(message).to.be.equals("nametag is not ok");
|
||||||
payload2,
|
|
||||||
(inboundMessageNametagBuffer = bobHSResult.nametagsInbound)
|
|
||||||
).get();
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user