How to disect OpenSSL error returned from decrypt_aead?


#1

Hello,

I am fairly new to the rust programming language and in an attempt to learn more I started a small project that requires decryption of text encrypted using sjcl. I used the demo to encrypt a piece of text using the following parameters:

  • password: “password”
  • salt: 3B889F6A 5CE3FC4B
  • key: 7DED638F DD30ACDB 4A34D153 48F12D95 BB388A7E 8CB9C35B 8D9C9009 89454E1E
  • iv: ECCFB278 E13D4DA6 695BBD75 77C61F7C
  • message: “Hallo Welt!”

gaining this output:

    {"iv":"7M+yeOE9TaZpW711d8YffA==",
    "v":1,
    "iter":1000,
    "ks":256,
    "ts":64,
    "mode":"ccm",
    "adata":"",
    "cipher":"aes",
    "salt":"O4ifalzj/Es=",
    "ct":"Lsbc3V06Fruulq83CRSiD2dohA=="}

Since I haven’t done anything with the OpenSSL API I have written a small C++ program to check it out. It decrypts the message above perfectly fine. After, I recreated the same program in rust using the OpenSSL crate.

    extern crate base64;
    extern crate hex;
    extern crate openssl;

    use openssl::symm::{decrypt_aead, Cipher};
    use openssl::hash::MessageDigest;
    use openssl::pkcs5::pbkdf2_hmac;

    fn main() {
        let salt = base64::decode(r#"O4ifalzj/Es="#).unwrap();
        let mut key = vec![0; 32];
        assert!(pbkdf2_hmac(b"password", &salt, 1000, MessageDigest::sha256(), &mut key).is_ok());
        let tmp = base64::decode(r#"Lsbc3V06Fruulq83CRSiD2dohA=="#).unwrap();
        let len = tmp.len() - (64 / 8);
        let ct = &tmp[..len];
        let tag = &tmp[len..];
        let iv = base64::decode(r#"7M+yeOE9TaZpW711d8YffA=="#).unwrap();
        let nonce = &iv[..(15 - 2)];

        let c = Cipher::aes_256_ccm();
        match decrypt_aead(c, &key, Some(&nonce), &Vec::new(), &ct, &tag) {
            Ok(plaintext) => println!("plaintext: {}", hex::encode_upper(plaintext)),
            Err(err) => println!("Error: {}", err),
        }
    }

Generating the key works perfectly fine and all the input vector look Ok compared to my other prorgam, but decrypt_aead returns with an error. It just tells OpenSSL error, the error stack is empty, and I do not know how to interpret it.
Did I do some rockie mistakes when passing the input vectors? I had a look at the tests in the OpenSSL crate, but I am missing the problem here. Since the parameters work fine, when using the OpenSSL library directly, the problem should be in how I use rust or the crate.
Any inputs for me?

Thanks,
Florian


#2

Can you show the equivalent C++ code that you wrote?


#3

An OpenSSL error with no extra error info is usually due to a tag validation failure.


#4

I uploaded the C++ equivalent to GitHub.

The Rust wrapper uses under the hood different API calls then I do, but I still have to figure out, what makes the difference.


#5

That code never calls EVP_DecryptFinal which is what actually performs the tag check.


#6

That is correct – I updated the C++ code – and if I call final it returns an error. Hence, the problem is not me using Rust, but me using OpenSSL :wink: Thanks a lot!

I will try to figure how this ought to work, and hopefully post later a working Rust example to conclude, though it is not strictly a Rust problem.