diff --git a/lib/internal/crypto/util.js b/lib/internal/crypto/util.js index 70e1027946190a..74ab59d3f9ec86 100644 --- a/lib/internal/crypto/util.js +++ b/lib/internal/crypto/util.js @@ -696,7 +696,7 @@ function bigIntArrayToUnsignedInt(input) { result |= input[n] << 8 * n_reversed; } - return result; + return result >>> 0; } function bigIntArrayToUnsignedBigInt(input) { diff --git a/test/parallel/test-webcrypto-util.js b/test/parallel/test-webcrypto-util.js index 89d8575e20ddbd..a1f79f21e51e49 100644 --- a/test/parallel/test-webcrypto-util.js +++ b/test/parallel/test-webcrypto-util.js @@ -8,9 +8,28 @@ if (!common.hasCrypto) const assert = require('assert'); const { + bigIntArrayToUnsignedInt, normalizeAlgorithm, } = require('internal/crypto/util'); +// bigIntArrayToUnsignedInt must return an unsigned 32-bit value even when +// the most significant byte has its top bit set. Otherwise the signed `<<` +// operator yields a negative Int32 for inputs like [0x80, 0x00, 0x00, 0x01]. +{ + assert.strictEqual( + bigIntArrayToUnsignedInt(new Uint8Array([0x80, 0x00, 0x00, 0x01])), + 0x80000001); + assert.strictEqual( + bigIntArrayToUnsignedInt(new Uint8Array([0xff, 0xff, 0xff, 0xff])), + 0xffffffff); + assert.strictEqual( + bigIntArrayToUnsignedInt(new Uint8Array([1, 0, 1])), + 65537); + assert.strictEqual( + bigIntArrayToUnsignedInt(new Uint8Array([1, 0, 0, 0, 0])), + undefined); +} + { // Check that normalizeAlgorithm does not mutate object inputs. const algorithm = { name: 'ECDSA', hash: 'SHA-256' };