0

When dealing with cryptographic secrets (private keys, passwords, etc) it is desirable to not run these secrets through functions that do not run in constant time, in order to avoid the potential for side channel attacks. An example of this would be the encoding a Unicode string into bytes to be used as an input for a KDF.

In browser-based JavaScript, the API for encoding to UTF-8 is TextEncoder. However, the API gives no guarantees about the runtime characteristics of the function. I would assume that a general-purpose implementation will be optimized for performance, and will take any shortcuts that it can, thus influencing the runtime based on the input. Additionally, because UTF-8 generates variable-byte-length outputs depending on the codepoints used in the string, this looks like something that cannot be easily implemented in constant time at all, correct?

Thus, when encoding a password to bytes, to be used as input for a KDF, would it be preferrable and safe to encode to UTF-16 (the character encoding used internally by JavaScript) by calling charCodeAt(i) for every i between 0 and inputString.length? This should result in exactly 2*inputString.length bytes and its runtime should not be dependent on the contents of the string (unless I'm overlooking something).

function pwToBytes(pw: string): Uint16Array {
    const buf = new ArrayBuffer(pw.length * 2);
    const view = new Uint16Array(buf);
    const length = pw.length;
    for (let i=0; i < length; i++) {
        view[i] = pw.charCodeAt(i);
    }
    return view;
}
Danilo Bargen
  • 336
  • 1
  • 4
  • 11
  • I would argue that the timing difference for the password encoding is irrelevant for the use case. A proper KDF will use significantly more time, so that the timing difference in encoding will not be measurable by some attacker, making a side channel attack not feasible. But, given that the password does not magically turn up there might be other places preceding this one where the length of the password can be measured more reliably. – Steffen Ullrich Nov 15 '21 at 16:32
  • Yes, a timing side channel attack like this would be very hard to pull off in practice, so it probably has little relevance in real life. However, it probably makes sense to err on the side of caution and choose an encoding that can be implemented in constant time. – Danilo Bargen Nov 15 '21 at 17:34

0 Answers0