Every CVE Search/ Get API key

CVE-2026-22698

RustCrypto SM2-PKE has 32-bit Biased Nonce Vulnerability

8.7 High

RustCrypto: Elliptic Curves is general purpose Elliptic Curve Cryptography (ECC) support, including types and traits for representing various elliptic curve forms, scalars, points, and public/secret keys composed thereof. In versions 0.14.0-pre.0 and 0.14.0-rc.0, a critical vulnerability exists in the SM2 Public Key Encryption (PKE) implementation where the ephemeral nonce k is generated with severely reduced entropy. A unit mismatch error causes the nonce generation function to request only 32 bits of randomness instead of the expected 256 bits. This reduces the security of the encryption from a 128-bit level to a trivial 16-bit level, allowing a practical attack to recover the nonce k and decrypt any ciphertext given only the public key and ciphertext. This issue has been patched via commit e4f7778.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.27%Up 0.2 points since Jan 10, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.7

RustCrypto SM2-PKE has 32-bit Biased Nonce Vulnerability

RustCrypto: Elliptic Curves is general purpose Elliptic Curve Cryptography (ECC) support, including types and traits for representing various elliptic curve forms, scalars, points, and public/secret keys composed thereof. In versions 0.14.0-pre.0 and 0.14.0-rc.0, a critical vulnerability exists in the SM2 Public Key Encryption (PKE) implementation where the ephemeral nonce k is generated with severely reduced entropy. A unit mismatch error causes the nonce generation function to request only 32 bits of randomness instead of the expected 256 bits. This reduces the security of the encryption from a 128-bit level to a trivial 16-bit level, allowing a practical attack to recover the nonce k and decrypt any ciphertext given only the public key and ciphertext. This issue has been patched via commit e4f7778.

Record
CVE-2026-22698
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-331
Updated
2026-11-02
EUVDEUVD-2026-1876 8.7

RustCrypto: Elliptic Curves is general purpose Elliptic Curve Cryptography (ECC) support, including types and traits for representing various elliptic curve forms, scalars, points, and public/secret keys composed thereof. In versions 0.14.0-pre.0 and 0.14.0-rc.0, a critical vulnerability exists in the SM2 Public Key Encryption (PKE) implementation where the ephemeral nonce k is generated with severely reduced entropy. A unit mismatch error causes the nonce generation function to request only 32 bits of randomness instead of the expected 256 bits. This reduces the security of the encryption from a 128-bit level to a trivial 16-bit level, allowing a practical attack to recover the nonce k and decrypt any ciphertext given only the public key and ciphertext. This issue has been patched via commit e4f7778.

Record
EUVD-2026-1876
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-w3g8-fp6j-wvqw 8.7

SM2-PKE has 32-bit Biased Nonce Vulnerability

Summary

A critical vulnerability exists in the SM2 Public Key Encryption (PKE) implementation where the ephemeral nonce k is generated with severely reduced entropy. A unit mismatch error causes the nonce generation function to request only 32 bits of randomness instead of the expected 256 bits. This reduces the security of the encryption from a 128-bit level to a trivial 16-bit level, allowing a practical attack to recover the nonce k and decrypt any ciphertext given only the public key and ciphertext.

Affected Versions

This vulnerability is introduced in commit: Commit 4781762 on Sep 6, 2024, which is over a year ago.

Details

The root cause of this vulnerability is a unit mismatch in the encrypt function located in sm2/src/pke/encrypting.rs.

  1. The code correctly calculates the byte-length of the curve order (256 bits / 8 = 32 bytes) and stores it in a constant N_BYTES.
    const N_BYTES: u32 = Sm2::ORDER.as_ref().bits().div_ceil(8); // Value is 32 (bytes)
    
  2. However, this N_BYTES value is then passed to the next_k helper function, which incorrectly interprets this value as a bit length.
    let k = Scalar::from_uint(&next_k(rng, N_BYTES)?).unwrap();
    
  3. Inside next_k, the bit_length parameter (which holds the value 32) is passed directly to U256::try_random_bits, a function that generates a random number with the specified number of bits.
    fn next_k<R: TryCryptoRng + ?Sized>(rng: &mut R, bit_length: u32) -> Result<U256> {
        let k = U256::try_random_bits(rng, bit_length).map_err(|_| Error)?;
        // ...
    }
    
    As a result, the ephemeral nonce k is generated with only 32 bits of entropy, with its upper 224 bits being zero. This catastrophic loss of randomness makes the encryption scheme insecure.

PoC

A proof-of-concept demonstrating the feasibility of this attack is provided in examples/bsgs_recover.rs. The PoC performs the following steps:

  1. Encrypt a Message: It uses the vulnerable EncryptingKey::encrypt function to encrypt a sample message.
  2. Extract Ephemeral Public Key: It parses the ciphertext to extract C1, which is the ephemeral public key [k]G.
  3. Recover Nonce k: It runs a Baby-Step Giant-Step (BSGS) algorithm to search the reduced 2^32 search space for the nonce k. This attack is computationally feasible on modern hardware in seconds with time complexity O(2^16).
  4. Decrypt without Secret Key: Once k is recovered, it computes the shared secret [k]PB (where PB is the recipient's public key) and successfully decrypts the ciphertext without access to the recipient's secret key.

examples/bsgs_recover.rs

//! Example: Recover low-entropy nonce k via Baby-Step Giant-Step (BSGS)
//!
//! This example intentionally demonstrates an attack on the vulnerable
//! `EncryptingKey::encrypt` implementation which (in the current repository
//! state) may generate k with only 32 bits of entropy. The example:
//! - Generates a key pair and encrypts a short plaintext.
//! - Extracts C1 from the ciphertext (ephemeral public key [k]G).
//! - Runs BSGS over the reduced search space 2^32 to recover k and decrypt: time O(2^16), space O(2^16).
//!

use std::collections::HashMap;
use std::error::Error;

use rand_core::OsRng;

use sm2::{
    pke::Mode,
    pke::EncryptingKey,
    PublicKey,
    SecretKey,
    AffinePoint,
    ProjectivePoint,
    Scalar,
};
use elliptic_curve::bigint::U256;
use elliptic_curve::{Group, Curve};
use elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint};
use sm3::{Sm3, Digest};

/// Baby-step giant-step over the 32-bit search space.
fn bsgs_recover_k(c1: &AffinePoint) -> Option<U256> {
    //…
Record
GHSA-w3g8-fp6j-wvqw
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-331
Updated
2026-11-02
NVD 8.7

RustCrypto: Elliptic Curves is general purpose Elliptic Curve Cryptography (ECC) support, including types and traits for representing various elliptic curve forms, scalars, points, and public/secret keys composed thereof. In versions 0.14.0-pre.0 and 0.14.0-rc.0, a critical vulnerability exists in the SM2 Public Key Encryption (PKE) implementation where the ephemeral nonce k is generated with severely reduced entropy. A unit mismatch error causes the nonce generation function to request only 32 bits of randomness instead of the expected 256 bits. This reduces the security of the encryption from a 128-bit level to a trivial 16-bit level, allowing a practical attack to recover the nonce k and decrypt any ciphertext given only the public key and ciphertext. This issue has been patched via commit e4f7778.

Record
CVE-2026-22698
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-331
Updated
2026-11-02
OSV 8.7

RustCrypto SM2-PKE has 32-bit Biased Nonce Vulnerability

RustCrypto: Elliptic Curves is general purpose Elliptic Curve Cryptography (ECC) support, including types and traits for representing various elliptic curve forms, scalars, points, and public/secret keys composed thereof. In versions 0.14.0-pre.0 and 0.14.0-rc.0, a critical vulnerability exists in the SM2 Public Key Encryption (PKE) implementation where the ephemeral nonce k is generated with severely reduced entropy. A unit mismatch error causes the nonce generation function to request only 32 bits of randomness instead of the expected 256 bits. This reduces the security of the encryption from a 128-bit level to a trivial 16-bit level, allowing a practical attack to recover the nonce k and decrypt any ciphertext given only the public key and ciphertext. This issue has been patched via commit e4f7778.

Record
CVE-2026-22698
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-331
Updated
2026-11-02
OSVGHSA-w3g8-fp6j-wvqw 8.7

SM2-PKE has 32-bit Biased Nonce Vulnerability

Summary

A critical vulnerability exists in the SM2 Public Key Encryption (PKE) implementation where the ephemeral nonce k is generated with severely reduced entropy. A unit mismatch error causes the nonce generation function to request only 32 bits of randomness instead of the expected 256 bits. This reduces the security of the encryption from a 128-bit level to a trivial 16-bit level, allowing a practical attack to recover the nonce k and decrypt any ciphertext given only the public key and ciphertext.

Affected Versions

This vulnerability is introduced in commit: Commit 4781762 on Sep 6, 2024, which is over a year ago.

Details

The root cause of this vulnerability is a unit mismatch in the encrypt function located in sm2/src/pke/encrypting.rs.

  1. The code correctly calculates the byte-length of the curve order (256 bits / 8 = 32 bytes) and stores it in a constant N_BYTES.
    const N_BYTES: u32 = Sm2::ORDER.as_ref().bits().div_ceil(8); // Value is 32 (bytes)
    
  2. However, this N_BYTES value is then passed to the next_k helper function, which incorrectly interprets this value as a bit length.
    let k = Scalar::from_uint(&next_k(rng, N_BYTES)?).unwrap();
    
  3. Inside next_k, the bit_length parameter (which holds the value 32) is passed directly to U256::try_random_bits, a function that generates a random number with the specified number of bits.
    fn next_k<R: TryCryptoRng + ?Sized>(rng: &mut R, bit_length: u32) -> Result<U256> {
        let k = U256::try_random_bits(rng, bit_length).map_err(|_| Error)?;
        // ...
    }
    
    As a result, the ephemeral nonce k is generated with only 32 bits of entropy, with its upper 224 bits being zero. This catastrophic loss of randomness makes the encryption scheme insecure.

PoC

A proof-of-concept demonstrating the feasibility of this attack is provided in examples/bsgs_recover.rs. The PoC performs the following steps:

  1. Encrypt a Message: It uses the vulnerable EncryptingKey::encrypt function to encrypt a sample message.
  2. Extract Ephemeral Public Key: It parses the ciphertext to extract C1, which is the ephemeral public key [k]G.
  3. Recover Nonce k: It runs a Baby-Step Giant-Step (BSGS) algorithm to search the reduced 2^32 search space for the nonce k. This attack is computationally feasible on modern hardware in seconds with time complexity O(2^16).
  4. Decrypt without Secret Key: Once k is recovered, it computes the shared secret [k]PB (where PB is the recipient's public key) and successfully decrypts the ciphertext without access to the recipient's secret key.

examples/bsgs_recover.rs

//! Example: Recover low-entropy nonce k via Baby-Step Giant-Step (BSGS)
//!
//! This example intentionally demonstrates an attack on the vulnerable
//! `EncryptingKey::encrypt` implementation which (in the current repository
//! state) may generate k with only 32 bits of entropy. The example:
//! - Generates a key pair and encrypts a short plaintext.
//! - Extracts C1 from the ciphertext (ephemeral public key [k]G).
//! - Runs BSGS over the reduced search space 2^32 to recover k and decrypt: time O(2^16), space O(2^16).
//!

use std::collections::HashMap;
use std::error::Error;

use rand_core::OsRng;

use sm2::{
    pke::Mode,
    pke::EncryptingKey,
    PublicKey,
    SecretKey,
    AffinePoint,
    ProjectivePoint,
    Scalar,
};
use elliptic_curve::bigint::U256;
use elliptic_curve::{Group, Curve};
use elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint};
use sm3::{Sm3, Digest};

/// Baby-step giant-step over the 32-bit search space.
fn bsgs_recover_k(c1: &AffinePoint) -> Option<U256> {
    //…
Record
GHSA-w3g8-fp6j-wvqw
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-331
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
sm2
crates.io
0.14.0-pre.0 to 0.14.0-rc.4 None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-22698 is a high vulnerability (CVSS 8.7) in Rustcrypto Elliptic-curves, published January 9, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.27%, the 19th percentile. No source names a fixed version.

References

Show 4 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open