Skip to content

Commit 27c7f4d

Browse files
deepview-autofixclaudeChALkeR
authored
crypto: fix unsigned conversion of 4-byte RSA publicExponent
`bigIntArrayToUnsignedInt` used the signed `<<` operator, so when the most significant byte of a 4-byte input had its top bit set (e.g. `[0x80, 0x00, 0x00, 0x01]`) the result was a negative Int32 instead of the intended unsigned 32-bit value. This caused any RSA `publicExponent` exactly 4 bytes long with the top bit set to be parsed incorrectly. Coerce the final value with `>>> 0` and add a unit test. Assisted-by: Claude <[email protected]> Co-Authored-By: Claude <[email protected]> Co-Authored-By: DeepView Autofix <[email protected]> Co-Authored-By: Nikita Skovoroda <[email protected]> Signed-off-by: Nikita Skovoroda <[email protected]> PR-URL: #62839 Reviewed-By: Filip Skokan <[email protected]>
1 parent 48dce8b commit 27c7f4d

2 files changed

Lines changed: 20 additions & 1 deletion

File tree

lib/internal/crypto/util.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ function bigIntArrayToUnsignedInt(input) {
698698
result |= input[n] << 8 * n_reversed;
699699
}
700700

701-
return result;
701+
return result >>> 0;
702702
}
703703

704704
function bigIntArrayToUnsignedBigInt(input) {

test/parallel/test-webcrypto-util.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,29 @@ if (!common.hasCrypto)
88
const assert = require('assert');
99

1010
const {
11+
bigIntArrayToUnsignedInt,
1112
normalizeAlgorithm,
1213
validateKeyOps,
1314
} = require('internal/crypto/util');
1415

16+
// bigIntArrayToUnsignedInt must return an unsigned 32-bit value even when
17+
// the most significant byte has its top bit set. Otherwise the signed `<<`
18+
// operator yields a negative Int32 for inputs like [0x80, 0x00, 0x00, 0x01].
19+
{
20+
assert.strictEqual(
21+
bigIntArrayToUnsignedInt(new Uint8Array([0x80, 0x00, 0x00, 0x01])),
22+
0x80000001);
23+
assert.strictEqual(
24+
bigIntArrayToUnsignedInt(new Uint8Array([0xff, 0xff, 0xff, 0xff])),
25+
0xffffffff);
26+
assert.strictEqual(
27+
bigIntArrayToUnsignedInt(new Uint8Array([1, 0, 1])),
28+
65537);
29+
assert.strictEqual(
30+
bigIntArrayToUnsignedInt(new Uint8Array([1, 0, 0, 0, 0])),
31+
undefined);
32+
}
33+
1534
{
1635
// Check that normalizeAlgorithm does not mutate object inputs.
1736
const algorithm = { name: 'ECDSA', hash: 'SHA-256' };

0 commit comments

Comments
 (0)