CVE-2020-14968
Description
An issue was discovered in the jsrsasign package before 8.0.17 for Node.js. Its RSASSA-PSS (RSA-PSS) implementation does not detect signature manipulation/modification by prepending '\0' bytes to a signature (it accepts these modified signatures as valid). An attacker can abuse this behavior in an application by creating multiple valid signatures where only one signature should exist. Also, an attacker might prepend these bytes with the goal of triggering memory corruption issues.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
The jsrsasign library's RSASSA-PSS verification fails to reject signatures with prepended null bytes, allowing signature forgery and potential memory corruption.
The vulnerability lies in the jsrsasign library (versions before 8.0.17), where the RSASSA-PSS signature verification implementation does not check for prepended null bytes. As a result, an attacker can take a valid signature and prepend one or more \0 bytes, and the library will still accept the modified signature as valid [1][2][3].
An attacker can exploit this by creating multiple distinct signatures from a single valid signature by varying the number of prepended null bytes. This breaks the expected property that each message should have a unique signature. Additionally, the description notes that prepending null bytes might lead to memory corruption issues in certain conditions [2][3].
The impact includes the ability to forge signatures or generate multiple valid signatures for the same message, undermining the integrity guarantees of RSA-PSS. The potential memory corruption could lead to denial of service or more serious security breaches depending on the application [2].
The issue is fixed in jsrsasign version 8.0.17 [2]. Users should upgrade immediately. Note that the jsrsasign project has announced end of support on June 3, 2026 [4].
- jsrsasign JavaScript API Reference - RSAKey
- NVD - CVE-2020-14968
- The RSA-PSS implementation does not detect signature modification (prepending "0" bytes) to the signature
- GitHub - kjur/jsrsasign: CAUTION: END OF SUPPORT ON 3 JUN 2026. The 'jsrsasign' (RSA-Sign JavaScript Library) is an opensource free cryptography library supporting RSA/RSAPSS/ECDSA/DSA signing/validation, ASN.1, PKCS#1/5/8 private/public key, X.509 certificate, CRL, OCSP, CMS SignedData, TimeStamp, CAdES and JSON Web Signature/Token in pure JavaScript.
AI Insight generated on May 21, 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.
| Package | Affected versions | Patched versions |
|---|---|---|
jsrsasignnpm | >= 3.0.0, < 8.0.17 | 8.0.17 |
Affected products
2- jsrsasign/jsrsasigndescription
Patches
13bcc088c7276#442 RSAGenerate key length issue fix
5 files changed · +63 −6
ChangeLog.txt+5 −0 modified@@ -6,8 +6,13 @@ ChangeLog for jsrsasign - allow alternative algorithms to sign CRLs (#440) - src/asn1cms.js - improve CMSUtil.newSignedData helper with detached signatures (#441) + - ext/rsa2.js + - RSAGenerate fixed for not having requesting key length (#442) - sample_node - pemtobin was fixed for pemtohex function + - test + - qunit-do-rsagenkeylen.html new test code for (#442) + - index.html, qunit-do-x509.html link update extended Authority/SubjectKeyIdentifier support * Changes from 8.0.15 to 8.0.16 (2020-Mar-29)
ext/rsa2.js+7 −5 modified@@ -202,11 +202,13 @@ function RSAGenerate(B,E) { var phi = p1.multiply(q1); if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { this.n = this.p.multiply(this.q); // this.n = p * q - this.d = ee.modInverse(phi); // this.d = - this.dmp1 = this.d.mod(p1); // this.dmp1 = d mod (p - 1) - this.dmq1 = this.d.mod(q1); // this.dmq1 = d mod (q - 1) - this.coeff = this.q.modInverse(this.p); // this.coeff = (q ^ -1) mod p - break; + if (this.n.bitLength() == B) { + this.d = ee.modInverse(phi); // this.d = + this.dmp1 = this.d.mod(p1); // this.dmp1 = d mod (p - 1) + this.dmq1 = this.d.mod(q1); // this.dmq1 = d mod (q - 1) + this.coeff = this.q.modInverse(this.p); // this.coeff = (q ^ -1) mod p + break; + } } } this.isPrivate = true;
test/index.html+1 −0 modified@@ -69,6 +69,7 @@ <li><a href="qunit-do-keyutil-keyid.html">qunit-do-keyutil-keyid.html</a></li> <li><a href="qunit-do-package-jwths.html">qunit-do-package-jwths.html</a></li> <li><a href="qunit-do-package-rsa.html">qunit-do-package-rsa.html</a></li> +<li><a href="qunit-do-rsagenkeylen.html">qunit-do-rsagenkeylen.html</a></li> <li><a href="qunit-do-rsapem.html">qunit-do-rsapem.html</a></li> <li><a href="qunit-do-rsasign-pss.html">qunit-do-rsasign-pss.html</a></li> <li><a href="qunit-do-rsasign.html">qunit-do-rsasign.html</a></li>
test/qunit-do-rsagenkeylen.html+50 −0 added@@ -0,0 +1,50 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<title>QUnit for RSAKey genarated key length test</title> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> +<script type="text/javascript" src="jquery-1.4.2.min.js"></script> +<script type="text/javascript" src="qunit.js"></script> +<link rel="stylesheet" href="qunit.css" type="text/css" media="screen" /> + +<script src="../ext/jsbn.js"></script> +<script src="../ext/jsbn2.js"></script> +<script src="../ext/prng4.js"></script> +<script src="../ext/rng.js"></script> +<script src="../ext/rsa.js"></script> +<script src="../ext/rsa2.js"></script> + +<script> +$(document).ready(function(){ +//========================================================================= +module("RSAKey.generate() Test"); + +test("RSAGenerate 100 generated 512bit key size check test", function() { + var nbit = 512; + //var nbit = 1024; + //var nbit = 2048; + var isCorrectLength = true; + for (var i = 0; i < 100; i++) { + var key = new RSAKey(); + key.generate(nbit, '10001'); + if (key.n.bitLength() != nbit) isCorrectLength = false; + } + equal(isCorrectLength, true, "all 100 keys are " + nbit + "bit length"); +}); + +}); +</script> + +</head> +<body> +<div id="qunit"></div> +<div id="qunit-fixture">test markup</div> + +<p> +<a href="../">TOP</a> | +<a href="index.html">TEST INDEX</a> | +</p> + +</body> +</html>
test/qunit-do-x509.html+0 −1 modified@@ -494,6 +494,5 @@ </p> </body> -<center><p>© 2010-2017 Kenji Urushima</p></center> </html>
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
16- github.com/advisories/GHSA-q3gh-5r98-j4h3ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-14968ghsaADVISORY
- cve.mitre.org/cgi-bin/cvename.cgighsaWEB
- github.com/kjur/jsrsasign/commit/3bcc088c727658d7235854cd2a409a904cc2ce99ghsaWEB
- github.com/kjur/jsrsasign/issues/438ghsax_refsource_MISCWEB
- github.com/kjur/jsrsasign/releases/tag/8.0.17ghsax_refsource_MISCWEB
- github.com/kjur/jsrsasign/releases/tag/8.0.18ghsax_refsource_MISCWEB
- github.com/kjur/jsrsasign/security/advisories/GHSA-q3gh-5r98-j4h3ghsaWEB
- kjur.github.io/jsrsasignghsaWEB
- kjur.github.io/jsrsasign/mitrex_refsource_MISC
- kjur.github.io/jsrsasign/api/symbols/RSAKey.htmlghsaWEB
- security.netapp.com/advisory/ntap-20200724-0001ghsaWEB
- security.netapp.com/advisory/ntap-20200724-0001/mitrex_refsource_CONFIRM
- vuldb.comghsaWEB
- www.npmjs.com/advisories/1541ghsaWEB
- www.npmjs.com/package/jsrsasignghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.