RSA icon indicating copy to clipboard operation
RSA copied to clipboard

Message too long

Open PaulDotSH opened this issue 3 years ago • 1 comments

Hi, encrypting a 3789 byte size string with a 4096 bit public key will trigger a crash with the following message: "MessageTooLong" The padding I was using is pkcs1v15 What's the maximum size we can encrypt? Is the padding a factor? Also why is this so low, I remember encrypting pretty large strings using other software like gnupg

Rust 1.60, rsa "0.7.0", Windows 10

PaulDotSH avatar Oct 11 '22 07:10 PaulDotSH

Encrypting large messages using RSA is generally done by using RSA as a key encapsulation mechanism (e.g. RSA-KEM), and using it to communicate a symmetric key which is used to encrypt the larger message with a symmetric encryption cipher like AES-GCM.

tarcieri avatar Oct 11 '22 15:10 tarcieri

I'm currently having this issue as well

Basically, I'm trying to implement some library for Google Oauth 2.0 APIs, which requires some JWT implementation which uses SHA256withRSA as the signing algorithm. (Reference)

to get to my issue, I'm trying to sign the value of

{Base64url encoded header}.{Base64url encoded claim set}

i.e.

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

My current implementation is roughly

pub fn auth(header: String, body: String) {
    use pkcs8::DecodePrivateKey;
    let private_key = rsa::RsaPrivateKey::from_pkcs8_pem(PRIVATE_KEY).unwrap();
    let hash = private_key
        .sign(
            rsa::PaddingScheme::PKCS1v15Sign {
                hash_len: None,
                prefix: Box::default(),
            },
            format!("{header}.{body}").as_bytes(),
        )
        .unwrap();
}

which currently errored-out with thread 'main' panicked at 'called ``Result::unwrap()`` on an ``Err`` value: MessageTooLong' on the private_key.sign(...).unwrap() part

To be honest, I'm not an expert at how the library should be used haha, so I might need some help on how the sign() might need to be used, particularly how the value for the PaddingScheme::PKCS1v15Sign variant should be

I've searched a bit and found how the PaddingScheme could be used on rust-jwt-simple

fn padding_scheme(&self) -> rsa::PaddingScheme {
    rsa::PaddingScheme::new_pkcs1v15_sign(Some(rsa::Hash::SHA2_256))
}

but it seems that it uses older API (0.6.1) instead of current 0.7, since right now I can't pass the Some(rsa::Hash::SHA2_256) as the parameter to the new_pkcs1v15_sign constructor, so I'm kinda lost

Edit

ok writing this issue might've help me in solving the issue. I can pass the SHA256 into new_pkcs1v15_sign with

+    use sha2::Digest;
+    let mut digest = sha2::Sha256::new();
+    digest.update(format!("{header}.{body}").as_bytes());
+    let digest = digest.finalize();
    
let hash = private_key
    .sign(
-        rsa::PaddingScheme::PKCS1v15Sign {
-            hash_len: None,
-            prefix: Box::default(),
-        },
-        format!("{header}.{body}").as_bytes(),
+        rsa::PaddingScheme::new_pkcs1v15_sign::<sha2::Sha256>(),
+        &digest,
    )
    .unwrap();

with oid feature enabled!

sha2 = { version = "0.10", features = ["oid"] }

Previously I did try that too, but it'll throw some compile-error.

taufik-rama avatar Oct 17 '22 05:10 taufik-rama

@taufik-rama your issue is related to signing, not encryption. Specifically you were passing a message where a digest is expected.

The new signing API takes care of hashing for you. Looks like you got it figured out?

tarcieri avatar Oct 17 '22 16:10 tarcieri

yeah, I think I'll leave the comment for reference if other folks got a "MessageTooLong" error variant because of similar usecase

taufik-rama avatar Oct 17 '22 23:10 taufik-rama

Closing this with the suggestion of using a hybrid cryptosystem instead

tarcieri avatar Apr 24 '23 23:04 tarcieri