Hi there!
I have a very specific problem and I haven't been able to make it work, thus I'm here. I want to port the following NodeJS code to Rust:
const crypto = require('crypto');
const payload = "{\"ziplist\":{\"reqid\":\"CreatorId_RequestNumber\",\"reqtime\":\"2015-02-22T12:20:55.123Z\",\"name\":\"FileName.zip\",\"files\":[{\"url\":\"https://media3.gaggenau.com/Images/600x/MCIM03407410_gaggenau-ovens-landing-400-series-teaser.jpg\",\"path\":\"Directory1/Backofen.jpg\"}]}}";
const signature = "5ae0221981e1a3e66c5c7b990dd66c823d1c879fe8feb667c292c103115fa651c9f8496d8c5132e47527b91efc1a4fa1e7d0010326529db09197a881913d4fc3e5e04ac079a353e81e60ceda6fe76df11a5e7035a9da3a030a99ef5a8d96d0e2381634006c64713fa488d232f2b5d910a1a68b38e4affac90e6500ff2261a501aa0c8b460d817f76370abaeed36f4531bf4358d604f9f9738f987f3c9b858e8526cd4604840e7e1f73ebb4cfee412ec952ae7a48ed904d72302f360836a42ae47e43c27ade88871605b52acd9cbe02154d523ef64252e34d1e9798fe4cd452cf88442cdcebf74954b001ebeb83df28caab34583e543cc33729e3b4193c0e1542";
const verifier = crypto.createVerify('RSA-SHA512');
const public_key = fs.readFileSync('./public.pem', 'utf8');
verifier.update(payload, 'utf8');
console.log(verifier.verify(public_key, signature, 'hex'));
As you can see, I need to verify the validity of a signed JSON string using a public key (PKCS#8 RSA) and SHA512 as digest function. The formats of everything are non-negotiable.
I've looked at several crates decided to go with rsa
and landed on the following:
use rsa::{pkcs8::DecodePublicKey, sha2::{Digest, Sha512}, PublicKey, Pkcs1v15Sign};
fn main() {
let payload = "{\"ziplist\":{\"reqid\":\"CreatorId_RequestNumber\",\"reqtime\":\"2015-02-22T12:20:55.123Z\",\"name\":\"FileName.zip\",\"files\":[{\"url\":\"https://media3.gaggenau.com/Images/600x/MCIM03407410_gaggenau-ovens-landing-400-series-teaser.jpg\",\"path\":\"Directory1/Backofen.jpg\"}]}}";
let signature = "5ae0221981e1a3e66c5c7b990dd66c823d1c879fe8feb667c292c103115fa651c9f8496d8c5132e47527b91efc1a4fa1e7d0010326529db09197a881913d4fc3e5e04ac079a353e81e60ceda6fe76df11a5e7035a9da3a030a99ef5a8d96d0e2381634006c64713fa488d232f2b5d910a1a68b38e4affac90e6500ff2261a501aa0c8b460d817f76370abaeed36f4531bf4358d604f9f9738f987f3c9b858e8526cd4604840e7e1f73ebb4cfee412ec952ae7a48ed904d72302f360836a42ae47e43c27ade88871605b52acd9cbe02154d523ef64252e34d1e9798fe4cd452cf88442cdcebf74954b001ebeb83df28caab34583e543cc33729e3b4193c0e1542";
let scheme = Pkcs1v15Sign::new::<Sha512>();
let hash = Sha512::digest(payload);
let key = rsa::RsaPublicKey::read_public_key_pem_file("./public.pem").unwrap();
println!("{}", key.verify(scheme, &hash, signature.as_bytes()).is_ok());
}
Unfortunately the verification is not successful. I noted that the NodeJS algorithm takes in the message as utf-8 encoded string whereas rsa
requires me to provide a hash thereof as bytes. Also NodeJS takes the signature as utf-8 encoded hex string whereas rsa
just takes bytes. I'm assuming there's a screwup somewhere in the encoding or formatting but I'm not sure where to start looking.
Any help would be greatly appreciated! Also, I'm not married to this particular crate so if anyone can suggest a different one that solves my issue, I'd be just as thankful.