VYPR
Critical severityNVD Advisory· Published Mar 23, 2026· Updated Mar 23, 2026

CVE-2026-4599

CVE-2026-4599

Description

Versions of the package jsrsasign from 7.0.0 and before 11.1.1 are vulnerable to Incomplete Comparison with Missing Factors via the getRandomBigIntegerZeroToMax and getRandomBigIntegerMinToMax functions in src/crypto-1.1.js; an attacker can recover the private key by exploiting the incorrect compareTo checks that accept out-of-range candidates and thus bias DSA nonces during signature generation.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

DSA nonce generation in jsrsasign uses flawed compareTo checks, allowing out-of-range values that bias nonces and enable private key recovery.

Vulnerability

Overview

The vulnerability (CVE-2026-4599) resides in the getRandomBigIntegerZeroToMax and getRandomBigIntegerMinToMax functions in src/crypto-1.1.js of the jsrsasign library. The root cause is an incorrect comparison using the compareTo method: the code checks biMax.compareTo(biRand) != -1 to accept values within range, but compareTo can return negative integers other than -1 (e.g., -2, -3) when biRand > biMax. This causes out-of-range candidates to be accepted, breaking the rejection-sampling invariant and biasing the generated random numbers [1][2].

Exploitation

Details

This issue directly impacts DSA signature generation (via dsa-2.0.js), where these random helpers are used to produce nonces. An attacker who can observe multiple DSA signatures from the same key can leverage the non-uniform nonce distribution to recover the private key [1][2]. The attack is network-based (CVSS AV:N) but requires high attack complexity due to the need for many signatures and statistical analysis [2].

Impact

Successful exploitation allows an attacker to recover the DSA private key, enabling signature forgery and compromising the authentication and integrity guarantees provided by DSA [2]. The CVSS v3.1 score is 7.4 High, reflecting severe confidentiality and integrity impact [2].

Mitigation

The issue is patched in jsrsasign version 11.1.1 [2]. The fix as proposed in the report improves the comparison logic to properly reject out-of-range values [4]. Note that the project has announced end of support on 3 June 2026, and users are advised to upgrade to the latest patched version or migrate to a supported alternative [3].

AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
jsrsasignnpm
>= 7.0.0, < 11.1.111.1.1

Affected products

2

Patches

1
ee4b01347836

Merge pull request #647 from Kr0emer/fix/bug-003-dsa-nonce-compareto

https://github.com/kjur/jsrsasignKenji UrushimaFeb 20, 2026via ghsa
2 files changed · +34 2
  • src/crypto-1.1.js+2 2 modified
    @@ -391,7 +391,7 @@ KJUR.crypto.Util.getRandomBigIntegerZeroToMax = function(biMax) {
         var bitLenMax = biMax.bitLength();
         while (1) {
     	var biRand = KJUR.crypto.Util.getRandomBigIntegerOfNbits(bitLenMax);
    -	if (biMax.compareTo(biRand) != -1) return biRand;
    +	if (biMax.compareTo(biRand) >= 0) return biRand;
         }
     };
     
    @@ -415,7 +415,7 @@ KJUR.crypto.Util.getRandomBigIntegerZeroToMax = function(biMax) {
      */
     KJUR.crypto.Util.getRandomBigIntegerMinToMax = function(biMin, biMax) {
         var flagCompare = biMin.compareTo(biMax);
    -    if (flagCompare == 1) throw "biMin is greater than biMax";
    +    if (flagCompare > 0) throw "biMin is greater than biMax";
         if (flagCompare == 0) return biMin;
     
         var biDiff = biMax.subtract(biMin);
    
  • test/qunit-do-crypto.html+32 0 modified
    @@ -211,6 +211,22 @@
       equal(n, 1000, "1000 times success:" + n0 + ":" + n1 + ":" + n2 + ":" + n3);
     });
     
    +test("Util.getRandomBigIntegerZeroToMax rejects out-of-range candidate", function() {
    +  var fOrig = KJUR.crypto.Util.getRandomBigIntegerOfNbits;
    +  var aBiRand = [new BigInteger("200", 10), new BigInteger("42", 10)];
    +  var idx = 0;
    +  KJUR.crypto.Util.getRandomBigIntegerOfNbits = function(n) {
    +    return aBiRand[idx++];
    +  };
    +  try {
    +    var bi = KJUR.crypto.Util.getRandomBigIntegerZeroToMax(new BigInteger("100", 10));
    +    equal(bi.toString(10), "42", "returns in-range value");
    +    equal(idx >= 2, true, "retries when out-of-range candidate appears");
    +  } finally {
    +    KJUR.crypto.Util.getRandomBigIntegerOfNbits = fOrig;
    +  }
    +});
    +
     test("Util.getRandomBigIntegerMinToMax", function() {
       var bi15 = new BigInteger("15", 10);
       var bi18 = new BigInteger("18", 10);
    @@ -270,6 +286,22 @@
       equal(new BigInteger("-13", 10).modInverse(biM2).toString(10), "82", "-13 mod 97");
     });
     
    +test("Util.getRandomBigIntegerMinToMax throws for any positive compareTo", function() {
    +  var biMin = {
    +    compareTo: function(a) { return 2; }
    +  };
    +  var biMax = {
    +    subtract: function(a) { throw "subtract must not be called"; }
    +  };
    +  var ex = null;
    +  try {
    +    KJUR.crypto.Util.getRandomBigIntegerMinToMax(biMin, biMax);
    +  } catch (err) {
    +    ex = err;
    +  }
    +  equal(ex, "biMin is greater than biMax", "throws before subtraction");
    +});
    +
     test("MessageDigest test", function() {
       expect(10);
       var md1 = new KJUR.crypto.MessageDigest({"alg": "sha1", "prov": "cryptojs"});
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.