From 21a7bc5579e22423beabf47263461c1365be0d23 Mon Sep 17 00:00:00 2001 From: Michael Williams Date: Mon, 27 Nov 2023 15:30:24 +1300 Subject: [PATCH] use constant-time increment and isZero --- js/secret-channel/src/crypto-javascript.js | 24 +++++++++++++++++----- js/secret-channel/src/crypto-native.js | 12 +++++++++++ js/secret-channel/src/protocol.js | 15 +++++++------- js/secret-channel/src/util.js | 11 ---------- 4 files changed, 38 insertions(+), 24 deletions(-) delete mode 100644 js/secret-channel/src/util.js diff --git a/js/secret-channel/src/crypto-javascript.js b/js/secret-channel/src/crypto-javascript.js index 9925340..e00cf47 100644 --- a/js/secret-channel/src/crypto-javascript.js +++ b/js/secret-channel/src/crypto-javascript.js @@ -3,14 +3,11 @@ const { chacha20poly1305 } = require('@noble/ciphers/chacha') const debug = require('./debug') -const IS_NODE = - typeof process !== 'undefined' && - typeof process.versions !== 'undefined' && - typeof process.versions.node !== 'undefined' - module.exports = { encrypt, decrypt, + increment, + isZero, } function encrypt(keyArg, nonceArg, plaintextArg) { @@ -27,3 +24,20 @@ function encrypt(keyArg, nonceArg, plaintextArg) { function decrypt(key, nonce, ciphertext) { return chacha20poly1305(key, nonce).encrypt(ciphertext) } + +function increment(buf) { + const len = buf.length + let c = 1 + for (let i = 0; i < len; i++) { + c += buf[i] + buf[i] = c + c >>= 8 + } +} + +function isZero(buf) { + const len = buf.length + let d = 0 + for (let i = 0; i < len; i++) d |= buf[i] + return d === 0 +} diff --git a/js/secret-channel/src/crypto-native.js b/js/secret-channel/src/crypto-native.js index 84701a8..b52d730 100644 --- a/js/secret-channel/src/crypto-native.js +++ b/js/secret-channel/src/crypto-native.js @@ -3,6 +3,8 @@ const { crypto_aead_chacha20poly1305_ietf_encrypt: sodiumEncrypt, crypto_aead_chacha20poly1305_ietf_decrypt: sodiumDecrypt, crypto_aead_chacha20poly1305_ietf_ABYTES: ABYTES, + sodium_increment: sodiumIncrement, + sodium_is_zero: sodiumIsZero, } = require('sodium-native') const debug = require('./debug') @@ -10,6 +12,8 @@ const debug = require('./debug') module.exports = { encrypt, decrypt, + increment, + isZero, } function encrypt(key, nonce, plaintext) { @@ -25,3 +29,11 @@ function decrypt(key, nonce, ciphertext) { sodiumDecrypt(plaintext, null, ciphertext, null, nonce, key) return plaintext } + +function increment(buffer) { + sodiumIncrement(buffer) +} + +function isZero(buffer) { + return sodiumIsZero(buffer) +} diff --git a/js/secret-channel/src/protocol.js b/js/secret-channel/src/protocol.js index 13325f3..fba9753 100644 --- a/js/secret-channel/src/protocol.js +++ b/js/secret-channel/src/protocol.js @@ -1,19 +1,20 @@ const b4a = require('b4a') -const { incrementBuffer } = require('./util') const { KEY_SIZE, LENGTH_OR_END_PLAINTEXT, LENGTH_OR_END_CIPHERTEXT } = require('./constants') const NONCE_SIZE = 12 class StreamCounter { + #increment #nonce - constructor() { + constructor(increment) { + this.#increment = increment this.#nonce = b4a.alloc(NONCE_SIZE, 0) } next() { - incrementBuffer(this.#nonce) + this.#increment(this.#nonce) return this.#nonce } } @@ -31,7 +32,7 @@ class StreamEncrypter { } this.#key = key - this.#counter = new StreamCounter() + this.#counter = new StreamCounter(crypto.increment) } next(plaintext) { @@ -69,8 +70,6 @@ class StreamEncrypter { } } -const endOfStreamBytes = b4a.alloc(LENGTH_OR_END_PLAINTEXT, 0) - class StreamDecrypter { #crypto #key @@ -84,7 +83,7 @@ class StreamDecrypter { } this.#key = key - this.#counter = new StreamCounter() + this.#counter = new StreamCounter(crypto.increment) } lengthOrEnd(ciphertext) { @@ -96,7 +95,7 @@ class StreamDecrypter { const plaintext = this.#decrypt(ciphertext) - if (plaintext.equals(endOfStreamBytes)) { + if (this.#crypto.isZero(plaintext)) { // TODO delete the key return { type: 'end-of-stream', diff --git a/js/secret-channel/src/util.js b/js/secret-channel/src/util.js deleted file mode 100644 index fd4e272..0000000 --- a/js/secret-channel/src/util.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - incrementBuffer, -} - -// https://github.com/dominictarr/pull-box-stream/issues/9#issuecomment-307557323 -function incrementBuffer(buf) { - for (let i = 0, len = buf.length, c = 1; i < len; i++) { - buf[i] = c += buf[i] - c >>= 8 - } -}