http_sig/algorithm/
openssl.rs1use std::fmt;
2
3use openssl::hash::MessageDigest;
4use openssl::pkey::{PKey, Private, Public};
5use openssl::rsa::Padding;
6use openssl::rsa::Rsa;
7use openssl::sign::{Signer, Verifier};
8
9use crate::{HttpSignatureSign, HttpSignatureVerify};
10
11macro_rules! rsa_signature {
12 ({$sign_name:ident, $verify_name:ident}($hash_alg:ident) = $name:literal) => {
13 #[doc = "Implementation of the signing half of the '"]
14 #[doc = $name]
15 #[doc = "' HTTP signature scheme."]
16 pub struct $sign_name(PKey<Private>);
17
18 impl fmt::Debug for $sign_name {
19 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20 f.write_str(stringify!($sign_name))
21 }
22 }
23
24 #[doc = "Implementation of the verification half of the '"]
25 #[doc = $name]
26 #[doc = "' HTTP signature scheme."]
27 pub struct $verify_name(PKey<Public>);
28
29 impl fmt::Debug for $verify_name {
30 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31 f.write_str(stringify!($verify_name))
32 }
33 }
34
35 impl $sign_name {
36 pub fn new_pkcs8(private_key: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
39 Ok(Self(PKey::private_key_from_pkcs8(private_key)?))
40 }
41 pub fn new_der(private_key: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
44 Ok(Self(PKey::from_rsa(Rsa::private_key_from_der(
45 private_key,
46 )?)?))
47 }
48 pub fn new_pem(private_key: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
51 Ok(Self(PKey::from_rsa(Rsa::private_key_from_pem(
52 private_key,
53 )?)?))
54 }
55 }
56
57 impl $verify_name {
58 pub fn new_der(public_key: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
61 Ok(Self(PKey::from_rsa(Rsa::public_key_from_der(public_key)?)?))
62 }
63 pub fn new_pem(public_key: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
66 Ok(Self(PKey::from_rsa(Rsa::public_key_from_pem(public_key)?)?))
67 }
68 }
69
70 impl HttpSignatureSign for $sign_name {
71 fn http_sign(&self, bytes_to_sign: &[u8]) -> String {
72 let mut signer = Signer::new(MessageDigest::$hash_alg(), &self.0).unwrap();
73 signer.set_rsa_padding(Padding::PKCS1).unwrap();
74 let tag = signer
75 .sign_oneshot_to_vec(bytes_to_sign)
76 .expect("Signing to be infallible");
77 base64::encode(&tag)
78 }
79 }
80 impl HttpSignatureVerify for $verify_name {
81 fn http_verify(&self, bytes_to_verify: &[u8], signature: &str) -> bool {
82 let tag = match base64::decode(signature) {
83 Ok(tag) => tag,
84 Err(_) => return false,
85 };
86 let mut verifier = Verifier::new(MessageDigest::$hash_alg(), &self.0).unwrap();
87 verifier.set_rsa_padding(Padding::PKCS1).unwrap();
88 match verifier.verify_oneshot(&tag, bytes_to_verify) {
89 Ok(true) => true,
90 Ok(false) => false,
91 Err(e) => {
92 dbg!(e);
93 false
94 }
95 }
96 }
97 }
98 };
99}
100
101rsa_signature!({RsaSha256Sign, RsaSha256Verify}(sha256) = "rsa-sha256");
102rsa_signature!({RsaSha512Sign, RsaSha512Verify}(sha512) = "rsa-sha512");