Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IV Size Mismatch in AES-256-GCM Encryption Between Node.js and Rust #653

Closed
divyeshkakadiya-inventyv opened this issue Jan 24, 2025 · 3 comments

Comments

@divyeshkakadiya-inventyv

I am working with AES-256-GCM encryption in both Node.js and Rust using the aes_gcm library, but I am encountering an issue with the IV (Initialization Vector). When I use a 16-byte IV in Node.js with the crypto module, both encryption and decryption work fine. However, when I encrypt data in Node.js with a 16-byte IV and try to decrypt it in Rust, the Rust AES crate does not support a 16-byte IV. It only supports a 12-byte IV.

assertion left == right failed

left: 16*
right: 12*
Note: I can run with the RUST_BACKTRACE=1 environment variable to display a backtrace.

What is the reason behind this, and what would be the best solution to resolve this issue?

@tarcieri
Copy link
Member

tarcieri commented Jan 24, 2025

You haven't provided any code, but are likely using the Aes256Gcm type alias:

https://docs.rs/aes-gcm/latest/aes_gcm/type.Aes256Gcm.html

pub type Aes256Gcm = AesGcm<Aes256, U12>;

The second U12 parameter in this type alias is the nonce size, where the standard nonce size is 12-bytes (96-bits). Note for AEADs the term "nonce" is preferred over "IV", which is generally used with lower level block cipher modes of operation.

Unlike Node.js, this information is encoded in the type system, which prevents runtime errors around bad nonce sizes.

If you want to use 16-byte (256-bit) nonces, you need to make a new type alias.

use aes_gcm::aead::generic_array::typenum::U16;
use aes_gcm::aes::Aes256;

pub type Aes256GcmWith16ByteNonce = aes_gcm::AesGcm<Aes256, U16>;

Note that any nonce size other than 12-bytes carries some security risk: the larger nonce is run through GHASH first, which increases the risk of a collision and nonce reuse. You should always use a 12-byte nonce with AES-GCM unless you are trying to interoperate with a protocol which made the mistake of choosing a different size.

@divyeshkakadiya-inventyv
Copy link
Author

divyeshkakadiya-inventyv commented Jan 28, 2025

// Step 6: Convert IV to Nonce type
let nonce = convert_to_nonce(iv.as_slice().try_into().unwrap());

// Function to convert the IV to Nonce
pub fn convert_to_nonce(iv_bytes: &[u8; 16]) -> &GenericArray<u8, typenum::U12> {
Nonce::from_slice(iv_bytes)
}

assertion left == right failed
left: 16
right: 12
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

when the Nonce::from_slice is executed above error is generated

@newpavlov
Copy link
Member

Have you read your own code? You convert an array containing 16 bytes ([u8; 16]) into a generic array with 12 bytes (GenericArray<u8, typenum::U12>).

@newpavlov newpavlov closed this as not planned Won't fix, can't repro, duplicate, stale Jan 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants