//! Encryption and siging using PKCS#1.

use nettle_sys::{
    __gmpz_clear, __gmpz_init, nettle_rsa_decrypt_tr,
    nettle_rsa_sec_decrypt, nettle_rsa_encrypt,
    nettle_rsa_pkcs1_sign_tr, nettle_rsa_pkcs1_verify,
};
use std::mem::zeroed;

use crate::hash::insecure_do_not_use::{Md2, Md5, Sha1, Ripemd160};
use crate::hash::{Sha224, Sha256, Sha384, Sha512};
use crate::rsa::{PrivateKey, PublicKey};
use crate::{helper, Error, hash::Hash, random::Random, Result};

/// Marker trait for hash algorithms usable for PKCS#1 signatures.
pub trait Pkcs1Hash: Hash {
    /// Internal to `sign_pkcs1` and `verify_pkcs1`.
    fn oid(&self) -> &'static [u8];
}

/// ASN.1 OID for MD2
pub const ASN1_OID_MD2: &[u8] = &[
    0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
    0x02, 0x02, 0x05, 0x00, 0x04, 0x10,
];
/// ASN.1 OID for MD5
pub const ASN1_OID_MD5: &[u8] = &[
    0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
    0x02, 0x05, 0x05, 0x00, 0x04, 0x10,
];
/// ASN.1 OID for RipeMD160
pub const ASN1_OID_RIPEMD160: &[u8] = &[
    0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05,
    0x00, 0x04, 0x14,
];
/// ASN.1 OID for SHA1
pub const ASN1_OID_SHA1: &[u8] = &[
    0x30, 33, 0x30, 9, 0x06, 5, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0, 0x04,
    20,
];
/// ASN.1 OID for SHA224
pub const ASN1_OID_SHA224: &[u8] = &[
    0x30, 0x2D, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
    0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C,
];
/// ASN.1 OID for SHA256
pub const ASN1_OID_SHA256: &[u8] = &[
    0x30, 49, 0x30, 13, 0x06, 9, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
    0x02, 0x01, 0x05, 0, 0x04, 32,
];
/// ASN.1 OID for SHA384
pub const ASN1_OID_SHA384: &[u8] = &[
    0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
    0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30,
];
/// ASN.1 OID for SHA512
pub const ASN1_OID_SHA512: &[u8] = &[
    0x30, 81, 0x30, 13, 0x06, 9, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
    0x02, 0x03, 0x05, 0, 0x04, 64,
];

impl Pkcs1Hash for Md2 {
    fn oid(&self) -> &'static [u8] {
        ASN1_OID_MD2
    }
}

impl Pkcs1Hash for Md5 {
    fn oid(&self) -> &'static [u8] {
        ASN1_OID_MD5
    }
}

impl Pkcs1Hash for Sha1 {
    fn oid(&self) -> &'static [u8] {
        ASN1_OID_SHA1
    }
}

impl Pkcs1Hash for Ripemd160 {
    fn oid(&self) -> &'static [u8] {
        ASN1_OID_RIPEMD160
    }
}

impl Pkcs1Hash for Sha224 {
    fn oid(&self) -> &'static [u8] {
        ASN1_OID_SHA224
    }
}

impl Pkcs1Hash for Sha256 {
    fn oid(&self) -> &'static [u8] {
        ASN1_OID_SHA256
    }
}

impl Pkcs1Hash for Sha384 {
    fn oid(&self) -> &'static [u8] {
        ASN1_OID_SHA384
    }
}

impl Pkcs1Hash for Sha512 {
    fn oid(&self) -> &'static [u8] {
        ASN1_OID_SHA512
    }
}

/// Creates a PKCS#1.5 padded RSA signature for `digest_info || digest`.
pub fn sign_digest_pkcs1<R: Random>(
    public: &PublicKey,
    private: &PrivateKey,
    digest: &[u8],
    digest_info: &[u8],
    random: &mut R,
    signature: &mut [u8],
) -> Result<()> {
    unsafe {
        let mut sig = zeroed();
        let mut msg = vec![0u8; digest.len() + digest_info.len()];

        msg[0..digest_info.len()].clone_from_slice(digest_info);
        msg[digest_info.len()..].clone_from_slice(digest);

        __gmpz_init(&mut sig);

        if nettle_rsa_pkcs1_sign_tr(
            &public.context,
            &private.context,
            random.context(),
            Some(R::random_impl),
            msg.len(),
            msg.as_ptr(),
            &mut sig,
        ) == 1
        {
            helper::write_gmpz_into_slice(sig, signature, "signature")
        } else {
            __gmpz_clear(&mut sig);

            Err(Error::SigningFailed)
        }
    }
}

/// Verifies a PKCS#1.5 padded RSA signature for `digest_info || digest`.
pub fn verify_digest_pkcs1(
    public: &PublicKey,
    digest: &[u8],
    digest_info: &[u8],
    signature: &[u8],
) -> Result<bool> {
    unsafe {
        let mut sig = helper::convert_buffer_to_gmpz(signature);
        let mut msg = vec![0u8; digest.len() + digest_info.len()];

        msg[0..digest_info.len()].clone_from_slice(digest_info);
        msg[digest_info.len()..].clone_from_slice(digest);

        let res = nettle_rsa_pkcs1_verify(
            &public.context,
            msg.len(),
            msg.as_ptr(),
            &mut sig,
        ) == 1;

        __gmpz_clear(&mut sig);
        Ok(res)
    }
}

/// Signs the message hashed with `hash` using `public`/`private`, producing `signature`. The
/// `signature` buffer is expected to be of the size of the modulo of `public`.
///
/// The function signs the digest produced by `hash` after padding the digest using `EMSA-PKCS1-v1_5`.
pub fn sign_pkcs1<H: Hash + Pkcs1Hash, R: Random>(
    public: &PublicKey,
    private: &PrivateKey,
    hash: &mut H,
    random: &mut R,
    signature: &mut [u8],
) -> Result<()> {
    let mut dst = vec![0u8; hash.digest_size()];

    hash.digest(&mut dst);
    sign_digest_pkcs1(public, private, &dst, hash.oid(), random, signature)
}

/// Verifies `signature` of the data hashed by `hash` using `public`. Returns `true` if the
/// signature is valid.
///
/// The signature is expected to be padded using `EMSA-PKCS1-v1_5`.
pub fn verify_pkcs1<H: Hash + Pkcs1Hash>(
    public: &PublicKey,
    hash: &mut H,
    signature: &[u8],
) -> Result<bool> {
    let mut dst = vec![0u8; hash.digest_size()];

    hash.digest(&mut dst);
    verify_digest_pkcs1(public, &dst, hash.oid(), signature)
}

/// Encrypts `plaintext` using `public`, producing `ciphertext`. `ciphertext` must have
/// the same size as the modulo of `public`.
///
/// The plaintext is padded using `RSAES-PKCS1-v1_5`.
pub fn encrypt_pkcs1<R: Random>(
    public: &PublicKey,
    random: &mut R,
    plaintext: &[u8],
    ciphertext: &mut [u8],
) -> Result<()> {
    unsafe {
        let mut out = zeroed();

        __gmpz_init(&mut out);

        if nettle_rsa_encrypt(
            &public.context,
            random.context(),
            Some(R::random_impl),
            plaintext.len(),
            plaintext.as_ptr(),
            &mut out,
        ) == 1
        {
            helper::write_gmpz_into_slice(out, ciphertext, "ciphertext")
        } else {
            __gmpz_clear(&mut out);

            Err(Error::EncryptionFailed)
        }
    }
}

/// Decrypts `ciphertext` using `public`/`private`. Returns the
/// resulting plaintext.
///
/// The ciphertext expected to be padded using
/// `RSAES-PKCS1-v1_5`.
///
/// # Errors
///
/// Returns `InvalidArgument` if `plaintext`'s size is greater or
/// equal than `public`'s modulo.
pub fn decrypt_pkcs1<R: Random>(
    public: &PublicKey,
    private: &PrivateKey,
    random: &mut R,
    ciphertext: &[u8],
    plaintext: &mut [u8],
) -> Result<()> {
    if plaintext.len() >= public.modulo_bytes {
        return Err(Error::invalid_argument("plaintext"));
    }

    // Fill with random bytes prior to decryption as recommended by
    // Nettle's documentation.  Should the decryption fail, the
    // plaintext will be unusable.
    random.random(plaintext);

    let mut inp = helper::convert_buffer_to_gmpz(ciphertext);
    unsafe {
        // Try to decrypt it and ignore the return value as
        // recommended by Nettle's documentation.
        nettle_rsa_sec_decrypt(
            &public.context,
            &private.context,
            random.context(),
            Some(R::random_impl),
            plaintext.len(),
            plaintext.as_mut_ptr(),
            &mut inp,
        );
        __gmpz_clear(&mut inp);
    }
    Ok(())
}

/// Decrypts `ciphertext` using `public`/`private`. Returns the
/// resulting plaintext.
///
/// The ciphertext expected to be padded using `RSAES-PKCS1-v1_5`.
///
/// # <span style="color: red">Important note:</span>
///
/// Side-channel leakage from the caller's use of length and return
/// value may still provide an oracle useable for a
/// Bleichenbacher-style chosen ciphertext attack.
///
/// If you know the size of the plaintext in advance, it is better to
/// use [`decrypt_pkcs1`](fn.decrypt_pkcs1.html).
///
/// # Errors
///
/// Returns `DecryptionFailed` if the decryption failed.
pub fn decrypt_pkcs1_insecure<R: Random>(
    public: &PublicKey,
    private: &PrivateKey,
    random: &mut R,
    ciphertext: &[u8],
) -> Result<Box<[u8]>> {
    unsafe {
        let mut inp = helper::convert_buffer_to_gmpz(ciphertext);
        let mut buf = vec![0u8; public.modulo_bytes];
        let mut buf_len = public.modulo_bytes;
        let res = nettle_rsa_decrypt_tr(
            &public.context,
            &private.context,
            random.context(),
            Some(R::random_impl),
            &mut buf_len,
            buf.as_mut_ptr(),
            &mut inp,
        ) == 1;

        __gmpz_clear(&mut inp);

        if res {
            buf.truncate(buf_len);
            Ok(buf.into())
        } else {
            Err(Error::DecryptionFailed)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::random::Yarrow;

    #[test]
    fn pkcs1_ciphertext_too_short() {
        let mut rnd = Yarrow::default();
        let n = &b"\xc8\xa2\x06\x91\x82\x39\x4a\x2a\xb7\xc3\xf4\x19\x0c\x15\x58\x9c\x56\xa2\xd4\xbc\x42\xdc\xa6\x75\xb3\x4c\xc9\x50\xe2\x46\x63\x04\x84\x41\xe8\xaa\x59\x3b\x2b\xc5\x9e\x19\x8b\x8c\x25\x7e\x88\x21\x20\xc6\x23\x36\xe5\xcc\x74\x50\x12\xc7\xff\xb0\x63\xee\xbe\x53\xf3\xc6\x50\x4c\xba\x6c\xfe\x51\xba\xa3\xb6\xd1\x07\x4b\x2f\x39\x81\x71\xf4\xb1\x98\x2f\x4d\x65\xca\xf8\x82\xea\x4d\x56\xf3\x2a\xb5\x7d\x0c\x44\xe6\xad\x4e\x9c\xf5\x7a\x43\x39\xeb\x69\x62\x40\x6e\x35\x0c\x1b\x15\x39\x71\x83\xfb\xf1\xf0\x35\x3c\x9f\xc9\x91"[..];
        let e = &b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01"[..];
        let public = PublicKey::new(n, e).unwrap();
        let mut ciphertext = [0u8; 1];

        assert!(encrypt_pkcs1(&public, &mut rnd, &b"123"[..], &mut ciphertext)
            .is_err());
    }

    #[test]
    fn rsa_pkcs15_sign() {
        let mut rnd = Yarrow::default();
        let n = &b"\xc8\xa2\x06\x91\x82\x39\x4a\x2a\xb7\xc3\xf4\x19\x0c\x15\x58\x9c\x56\xa2\xd4\xbc\x42\xdc\xa6\x75\xb3\x4c\xc9\x50\xe2\x46\x63\x04\x84\x41\xe8\xaa\x59\x3b\x2b\xc5\x9e\x19\x8b\x8c\x25\x7e\x88\x21\x20\xc6\x23\x36\xe5\xcc\x74\x50\x12\xc7\xff\xb0\x63\xee\xbe\x53\xf3\xc6\x50\x4c\xba\x6c\xfe\x51\xba\xa3\xb6\xd1\x07\x4b\x2f\x39\x81\x71\xf4\xb1\x98\x2f\x4d\x65\xca\xf8\x82\xea\x4d\x56\xf3\x2a\xb5\x7d\x0c\x44\xe6\xad\x4e\x9c\xf5\x7a\x43\x39\xeb\x69\x62\x40\x6e\x35\x0c\x1b\x15\x39\x71\x83\xfb\xf1\xf0\x35\x3c\x9f\xc9\x91"[..];
        let e = &b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01"[..];
        let d = &b"\x5d\xfc\xb1\x11\x07\x2d\x29\x56\x5b\xa1\xdb\x3e\xc4\x8f\x57\x64\x5d\x9d\x88\x04\xed\x59\x8a\x4d\x47\x02\x68\xa8\x90\x67\xa2\xc9\x21\xdf\xf2\x4b\xa2\xe3\x7a\x3c\xe8\x34\x55\x50\x00\xdc\x86\x8e\xe6\x58\x8b\x74\x93\x30\x35\x28\xb1\xb3\xa9\x4f\x0b\x71\x73\x0c\xf1\xe8\x6f\xca\x5a\xee\xdc\x3a\xfa\x16\xf6\x5c\x01\x89\xd8\x10\xdd\xcd\x81\x04\x9e\xbb\xd0\x39\x18\x68\xc5\x0e\xde\xc9\x58\xb3\xa2\xaa\xef\xf6\xa5\x75\x89\x7e\x2f\x20\xa3\xab\x54\x55\xc1\xbf\xa5\x50\x10\xac\x51\xa7\x79\x9b\x1f\xf8\x48\x36\x44\xa3\xd4\x25"[..];
        let p = &b"\xd0\x6f\xfa\x56\x3b\xd0\xb8\xb9\x7f\x00\x72\xea\x07\x51\x03\xec\x1f\xf0\xb1\x7f\xd6\xbd\xaf\x94\xa7\x5a\xe6\x03\x59\x82\xf6\x80\x24\x9d\x77\xcc\x15\x96\xa6\x54\xf1\x4c\x51\x7a\x13\xb9\x5f\x1a\x8c\x5d\xe8\xcc\x84\xad\x38\xd2\xe6\xaa\x4f\xcd\x54\x1a\x32\xeb"[..];
        let q = &b"\xf6\x6a\x24\x68\xb1\x48\x1a\x0d\x6b\x60\x49\x67\xf0\x58\x03\x89\xd6\x06\x1f\x03\x3a\x9b\x57\xb7\x4d\x1b\xef\xe8\x10\x11\x98\x94\x5b\x80\x93\x04\x24\x1d\x02\xfd\x5f\x92\x1f\xe9\x59\xfb\xec\xdb\x18\x00\x54\x86\x9a\xdb\x17\xd3\x21\xf9\xd5\xd5\x98\x12\x3e\x73"[..];
        let public = PublicKey::new(n, e).unwrap();
        let private = PrivateKey::new(d, p, q, None).unwrap();

        {
            let m = &b"\xe8\x31\x27\x42\xae\x23\xc4\x56\xef\x28\xa2\x31\x42\xc4\x49\x08\x95\x83\x27\x65\xda\xdc\xe0\x2a\xfe\x5b\xe5\xd3\x1b\x00\x48\xfb\xee\xe2\xcf\x21\x8b\x17\x47\xad\x4f\xd8\x1a\x2e\x17\xe1\x24\xe6\xaf\x17\xc3\x88\x8e\x6d\x2d\x40\xc0\x08\x07\xf4\x23\xa2\x33\xca\xd6\x2c\xe9\xea\xef\xb7\x09\x85\x6c\x94\xaf\x16\x6d\xba\x08\xe7\xa0\x69\x65\xd7\xfc\x0d\x8e\x5c\xb2\x65\x59\xc4\x60\xe4\x7b\xc0\x88\x58\x9d\x22\x42\xc9\xb3\xe6\x2d\xa4\x89\x6f\xab\x19\x9e\x14\x4e\xc1\x36\xdb\x8d\x84\xab\x84\xbc\xba\x04\xca\x3b\x90\xc8\xe5"[..];
            let expected = &b"\x28\x92\x8e\x19\xeb\x86\xf9\xc0\x00\x70\xa5\x9e\xdf\x6b\xf8\x43\x3a\x45\xdf\x49\x5c\xd1\xc7\x36\x13\xc2\x12\x98\x40\xf4\x8c\x4a\x2c\x24\xf1\x1d\xf7\x9b\xc5\xc0\x78\x2b\xce\xdd\xe9\x7d\xbb\xb2\xac\xc6\xe5\x12\xd1\x9f\x08\x50\x27\xcd\x57\x50\x38\x45\x3d\x04\x90\x54\x13\xe9\x47\xe6\xe1\xdd\xdb\xeb\x35\x35\xcd\xb3\xd8\x97\x1f\xe0\x20\x05\x06\x94\x10\x56\xf2\x12\x43\x50\x3c\x83\xea\xdd\xe0\x53\xed\x86\x6c\x0e\x02\x50\xbe\xdd\xd9\x27\xa0\x82\x12\xaa\x8a\xc0\xef\xd6\x16\x31\xef\x89\xd8\xd0\x49\xef\xb3\x6b\xb3\x5f"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x4c\x95\x07\x3d\xac\x19\xd0\x25\x6e\xaa\xdf\xf3\x50\x59\x10\xe4\x31\xdd\x50\x01\x81\x36\xaf\xea\xf6\x90\xb7\xd1\x80\x69\xfc\xc9\x80\xf6\xf5\x41\x35\xc3\x0a\xcb\x76\x9b\xee\x23\xa7\xa7\x2f\x6c\xe6\xd9\x0c\xbc\x85\x8c\x86\xdb\xbd\x64\xba\x48\xa0\x7c\x6d\x7d\x50\xc0\xe9\x74\x6f\x97\x08\x6a\xd6\xc6\x8e\xe3\x8a\x91\xbb\xee\xeb\x22\x21\xaa\x2f\x2f\xb4\x09\x0f\xd8\x20\xd4\xc0\xce\x5f\xf0\x25\xba\x8a\xdf\x43\xdd\xef\x89\xf5\xf3\x65\x3d\xe1\x5e\xdc\xf3\xaa\x80\x38\xd4\x68\x69\x60\xfc\x55\xb2\x91\x7e\xc8\xa8\xf9\xa8"[..];
            let expected = &b"\x53\xab\x60\x0a\x41\xc7\x13\x93\xa2\x71\xb0\xf3\x2f\x52\x19\x63\x08\x7e\x56\xeb\xd7\xad\x04\x0e\x4e\xe8\xaa\x7c\x45\x0a\xd1\x8a\xc3\xc6\xa0\x5d\x4a\xe8\x91\x3e\x76\x3c\xfe\x96\x23\xbd\x9c\xb1\xeb\x4b\xed\x1a\x38\x20\x05\x00\xfa\x7d\xf3\xd9\x5d\xea\x48\x5f\x03\x2a\x0a\xb0\xc6\x58\x96\x78\xf9\xe8\x39\x1b\x5c\x2b\x13\x92\x99\x7a\xc9\xf8\x2f\x1d\x16\x88\x78\x91\x6a\xac\xe9\xac\x74\x55\x80\x80\x56\xaf\x81\x55\x23\x1a\x29\xf4\x29\x04\xb7\xab\x87\xa5\xd7\x1e\xd6\x39\x5e\xe0\xa9\xd0\x24\xb0\xca\x3d\x01\xfd\x71\x50"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\xe0\x75\xad\x4b\x0f\x9b\x5b\x20\x37\x6e\x46\x7a\x1a\x35\xe3\x08\x79\x3b\xa3\x8e\xd9\x83\xd0\x38\x87\xb8\xb8\x2e\xda\x63\x0e\x68\xb8\x61\x8d\xc4\x5b\x93\xde\x55\x55\xd7\xbc\xfe\xd2\x37\x56\x40\x1e\x61\xf5\x51\x67\x57\xde\x6e\xc3\x68\x7a\x71\x75\x5f\xb4\xa6\x6c\xfa\xa3\xdb\x0c\x9e\x69\xb6\x31\x48\x5b\x4c\x71\xc7\x62\xee\xa2\x29\xa0\x46\x9c\x73\x57\xa4\x40\x95\x07\x92\xba\x9c\xd7\xae\x02\x2a\x36\xb9\xa9\x23\xc2\xeb\xd2\xaa\x69\x89\x7f\x4c\xce\xba\x0e\x7a\xee\x97\x03\x3d\x03\x81\x07\x25\xa9\xb7\x31\x83\x3f\x27"[..];
            let expected = &b"\x64\x26\x09\xce\x08\x4f\x47\x92\x71\xdf\x59\x64\x80\x25\x2e\x2f\x89\x2b\x3e\x79\x82\xdf\xf9\x59\x94\xc3\xee\xda\x78\x7f\x80\xf3\xf6\x19\x8b\xbc\xe3\x3e\xc5\x51\x53\x78\xd4\xb5\x71\xd7\x18\x60\x78\xb7\x5b\x43\xae\xd1\x1d\x34\x25\x47\x38\x6c\x56\x96\xeb\x37\x99\xa0\xb2\x84\x75\xe5\x4c\xd4\xca\x7d\x03\x6d\xcd\x8a\x11\xf5\xe1\x08\x06\xf7\xd3\xb8\xcc\x4f\xcb\x3e\x93\xe8\x57\xbe\x95\x83\x44\xa3\x4e\x12\x68\x09\xc1\x5b\x3d\x33\x66\x1c\xf5\x7b\xf5\xc3\x38\xf0\x7a\xcc\xed\x60\xf1\x40\x19\x33\x5c\x15\x2d\x86\xb3\xb2"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x18\x50\x01\x55\xd2\xe0\x58\x7d\x15\x26\x98\xc0\x7b\xa4\x4d\x4f\x04\xaa\x9a\x90\x0b\x77\xce\x66\x78\xa1\x37\xb2\x38\xb7\x3b\x1a\xea\x24\xa4\x09\xdb\x56\x3c\xf6\x35\x20\x9a\xea\x73\x5d\x3b\x3c\x18\xd7\xd5\x9f\xa1\x67\xe7\x60\xb8\x5d\x95\xe8\xaa\x21\xb3\x88\x1b\x1b\x20\x76\xf9\xd1\x55\x12\xae\x4f\x3d\x6e\x9a\xcc\x48\x0e\xc0\x8a\xbb\xec\xbf\xfe\x4a\xbf\x05\x31\xe8\x7d\x3f\x66\xde\x1f\x13\xfd\x1a\xa4\x12\x97\xca\x58\xe8\x7b\x2a\x56\xd6\x39\x9a\x4c\x63\x8d\xf4\x7e\x4e\x85\x1c\x0e\xc6\xe6\xd9\x7a\xdd\xcd\xe3\x66"[..];
            let expected = &b"\x42\xf3\xc3\xc7\x5f\x65\xad\x42\x05\x7b\xfa\xc1\x31\x03\x83\x7b\xf9\xf8\x42\x7c\x6e\xbc\x22\xa3\xad\xf7\xb8\xe4\x7a\x68\x57\xf1\xcb\x17\xd2\xa5\x33\xc0\xa9\x13\xdd\x9a\x8b\xdc\x17\x86\x22\x23\x60\xcb\xd7\xe6\x4b\x45\xfc\xf5\x4f\x5d\xa2\xf3\x42\x30\xab\x48\x06\xa0\x87\xf8\xbe\x47\xf3\x5c\x4e\x8f\xee\x2e\x6a\xa2\x91\x9a\x56\x67\x9c\xe2\xa5\x28\xa4\x4b\xf8\x18\x62\x0d\x5b\x00\xb9\xab\x0e\x1c\x8d\x2d\x72\x2b\x53\xd3\xa8\xcc\xa3\x5a\x99\x0e\xd2\x55\x36\xea\x65\x33\x5e\x82\x53\xa5\x4a\x68\xa6\x4a\x37\x3e\x0e\xd7"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\xf7\xf7\x9f\x9d\xf2\x76\x0f\xc8\x3c\x73\xc7\xcc\xea\x7e\xae\x48\x2d\xcf\xa5\xe0\x2a\xcf\x05\xe1\x05\xdb\x48\x28\x3f\x44\x06\x40\x43\x9a\x24\xca\x3b\x2a\x48\x22\x28\xc5\x8f\x3f\x32\xc3\x83\xdb\x3c\x48\x47\xd4\xbc\xc6\x15\xd3\xca\xc3\xeb\x2b\x77\xdd\x80\x04\x5f\x0b\x7d\xb8\x82\x25\xea\x7d\x4f\xa7\xe6\x45\x02\xb2\x9c\xe2\x30\x53\x72\x6e\xa0\x08\x83\xea\x5d\x80\x50\x25\x09\xa3\xb2\xdf\x74\xd2\x14\x2f\x6e\x70\xde\x22\xd9\xa1\x34\xa5\x02\x51\xe1\xa5\x31\x79\x8e\x74\x7e\x9d\x38\x6f\xe7\x9a\xe1\xde\xa0\x9e\x85\x1b"[..];
            let expected = &b"\xac\x2a\xe6\x6b\xca\x1e\xc1\x2a\x66\xa2\x90\x9f\xe2\x14\x8a\x1d\x49\x2d\x1e\xdd\x00\x06\x3b\x8b\x33\xaf\x74\x76\x0d\xc4\x05\x67\x18\xfd\x50\x41\xd4\xdf\xee\x12\xbe\xc7\x08\x1a\xb1\xba\xb2\xd0\xeb\x27\x12\xf3\x34\x50\x9f\x68\x89\xb1\x9d\x75\xd1\xfd\x0f\xc6\x1b\xf1\x29\x76\x10\x9c\x36\x14\xc4\x60\x51\xe2\xa4\x01\xb2\x08\x80\xd6\xe6\x4a\xd6\xa4\x7f\x23\x93\x98\x03\xd1\x38\xaa\x0a\x44\xbc\x41\xba\x63\x03\x07\x46\x62\x22\x48\x77\x14\x31\xdf\xf9\x7e\x8a\x85\x6f\x0b\x61\xd1\x14\xf8\x13\x91\x1e\xe2\x29\x65\x51\x55"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x09\x9b\xf1\x7f\x16\xbc\xfd\x4c\x19\xb3\x4f\xec\xb4\xb3\x23\x3c\x9f\x9f\x98\x71\x8f\x67\xb3\x06\x5d\x95\xa5\xf8\x64\x23\x51\x36\x2b\x90\x09\x53\x44\x33\x98\x7f\x73\xce\x86\xb5\x13\x66\x97\x36\xb6\x52\x95\x35\x0c\x93\x4f\xd4\x06\x63\xe2\x4f\x3a\x10\x37\x77\x8a\x0b\xcd\x63\x00\x3c\xb9\x62\xfd\x99\xeb\x33\x93\xf7\xb2\x79\x2f\x20\x83\x69\x7b\x25\xf6\xc6\x82\xf6\x11\x0f\x16\x2f\xc9\xf7\x6e\x35\xc6\x15\x14\x82\x67\xdd\xff\x3d\x06\xcf\xfb\x0e\x7d\xee\x52\x30\xe8\x74\xa5\xc8\xad\xc4\x1b\x75\xba\xa0\xbe\x28\x0e\x9c"[..];
            let expected = &b"\x3a\x2b\x75\x71\x61\x92\x72\xb8\x1d\x35\x62\xa1\x1c\x64\x45\x02\x89\x44\x21\x58\x3e\x02\x87\x9f\x5a\x77\x59\xfb\x64\xec\x2a\xb8\x10\x5f\x7d\x11\x94\x7c\x8e\x4b\xfc\xa8\x72\x19\xe5\x29\x87\xaa\xd3\xb8\x1c\xbd\x48\x31\x66\xed\x78\x15\x2a\xf2\x44\x60\xc9\x08\x87\x9f\x34\xc8\x70\x57\x31\x27\xe3\x44\x8c\x8f\xbf\x43\x02\x83\x50\xc9\x75\xbb\xc3\xa9\x99\x19\x6a\x3e\x99\x61\x22\x8a\x2b\xb1\x5b\x49\x85\xe9\x5b\xba\x97\x0a\xc4\xad\x2a\xc5\xb4\x2a\xc5\x1d\xbc\x65\x09\xef\xfc\x13\x39\x66\x93\x98\x0f\xc8\x9b\xa4\x4c\x7b"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\xfb\x40\xa7\x3d\xc8\x2f\x16\x7f\x9c\x2b\xf9\x8a\x99\x1e\xa8\x2f\xdb\x01\x41\xdb\xad\x44\x87\x1a\xfd\x70\xf0\x5a\x0e\x0b\xf9\xf2\x6d\xbc\xbd\x62\x26\xaf\xc6\xdc\x37\x3b\x23\x04\x45\xc2\xba\xf5\x8e\xd9\xe0\x84\x1f\xa9\x27\xc8\x47\x95\x77\xda\x4b\x1e\x61\xd9\x5b\x03\xaf\x31\xc5\xac\x40\x1d\x69\xc8\x13\x6b\x6d\x36\xa1\x80\x32\x21\x70\x9b\x86\x70\xe5\x5e\x1b\x5d\x5a\x8a\x37\x63\x70\x0a\xae\x5e\xa6\x33\x0e\xee\x2b\x4a\x19\x1c\xf1\x46\x78\x40\x03\xd8\xad\x22\x18\xa9\x4a\x5f\x68\xe3\x60\x0e\xbe\xf2\x3b\xa4\xcf\x8c"[..];
            let expected = &b"\xb1\x03\x22\x60\x2c\x28\x4f\x40\x79\xe5\x09\xfa\xf3\xf4\x0a\x3d\x2a\xf3\xab\xef\x9f\x09\x17\x1f\xdd\x16\x46\x9d\x67\x9b\xb9\xad\xc7\xe2\xac\xb1\xad\xdb\x0b\xd5\xb3\x8b\x5c\x4d\x98\x6b\x43\xc7\x9b\x97\x24\xf6\x1e\x99\xb5\xb3\x03\x63\x0b\x62\xd0\xd8\xd5\xf7\x65\x77\xfe\x7e\xa3\x87\x71\x0b\x43\x78\x9e\xe1\xb3\x5b\x61\x4b\x69\x1f\x0a\x27\xb7\x3b\xaf\x6b\xc3\xf2\x8e\xc2\x10\xb9\xd3\xe4\xc5\xa2\x72\x9c\xc1\x20\x3b\x74\xef\x70\xe3\x15\xcf\xe5\xd0\x6e\x04\x0a\xee\x6b\x3d\x22\xd9\x1d\x6e\x22\x9f\x69\x0a\x96\x6d\xd9"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x97\xe7\x49\x60\xdb\xd9\x81\xd4\x6a\xad\xc0\x21\xa6\xcf\x18\x1d\xdd\xe6\xe4\xcf\xcb\x4b\x63\x82\x60\xc0\xa5\x19\xc4\x5f\xab\xa2\x99\xd0\xca\x2e\x80\xbf\x50\xdf\xde\x8d\x6a\x42\xe0\x46\x45\xdf\xbc\xd4\x74\x0f\x3a\x72\x92\x0e\x74\x63\x28\x51\xd9\xe3\xd0\x1a\x78\x5e\x9b\x49\x7c\xe0\xb1\x75\xf2\xcd\x37\x3b\xd3\xd2\x76\xd6\x3e\x1b\x39\xf0\x05\xc6\x76\xb8\x6b\x98\x31\x35\x2c\xef\x9e\xda\xbe\xf8\x86\x5a\xd7\x22\xeb\xbe\x2f\xd3\xef\xb4\x87\x59\xf2\x2a\xea\x23\xfb\x1b\x33\x31\x59\xa9\xcf\xc9\x8a\x6d\xc4\x6c\x5b\x0b"[..];
            let expected = &b"\x60\xeb\xc9\xe4\xe2\xe2\xb4\xfa\x6d\x31\xc5\x7d\x0b\x86\x83\x5e\x8d\x20\x1d\x21\xc2\x74\xcf\x54\x52\xcd\xd7\xef\x28\x57\xdc\x78\x0d\xde\x35\x26\xf3\x65\x8c\x4f\x2c\x87\x10\xea\xae\x48\x70\xd2\x75\x99\x7e\x5c\xbb\x26\x8e\x3b\xd2\x51\xf5\x43\xb8\x82\x8f\xeb\x85\xc2\x11\xc8\x58\xe4\x7a\x74\xcb\x12\x2d\xc1\x7f\x26\xfe\x92\xb4\xaf\xee\xcb\xf1\xe2\x0b\xea\x75\xc7\x94\xc0\x48\x2a\xa6\x53\x2e\x87\x95\x5d\xba\x24\x9f\x0f\xa6\x56\x2b\xdf\x8f\x4c\xcd\x8a\x63\xda\x69\xd1\xf3\x37\x52\x3f\x65\x20\x6f\xb8\xeb\x16\x31\x73"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x95\xd0\x46\x24\xb9\x98\x93\x8d\xd0\xa5\xba\x6d\x70\x42\xaa\x88\xa2\x67\x4d\xad\x43\x8a\x0d\x31\xab\xb7\x97\x9d\x8d\xe3\xde\xa4\x1e\x7e\x63\x58\x7a\x47\xb5\x9d\x43\x64\x33\xdd\x8b\xb2\x19\xfd\xf4\x5a\xbb\x90\x15\xa5\x0b\x4b\x20\x11\x61\xb9\xc2\xa4\x7c\x30\x4b\x80\xc4\x04\x0f\xb8\xd1\xfa\x0c\x62\x31\x00\xcd\xed\x66\x1b\x8e\xb5\x2f\xa0\xa0\xd5\x09\xa7\x0f\x3c\xf4\xbd\x83\x04\x7a\xd9\x64\xff\xee\x92\x41\x92\xf2\x8e\x73\xc6\x3b\x3e\xfd\x9c\x99\xc8\xb7\xa1\x31\x45\xac\xc3\x0d\x2d\xc0\x63\xd8\x0f\x96\xab\xe2\x86"[..];
            let expected = &b"\x85\x9c\xc4\xfc\xd1\xb8\x8c\xcd\xa6\x95\xb1\x23\x11\xcf\x8b\xdc\xa3\xb4\xc1\x35\xfa\xa1\x1f\x90\x53\xdc\x10\xf4\xbf\x12\xe5\xf2\x17\x9b\xe6\xab\x5a\xd9\x0f\x8d\x11\x5f\x5d\xf7\x95\xa7\x73\x40\xe2\x06\x62\x80\x9f\xa7\x32\xb9\x25\x60\xad\xcf\xfd\xb0\xdd\xb7\x2d\x33\x81\x1e\x94\xf8\x54\x33\x06\x80\xf2\xb2\x38\x30\x09\x95\xa9\x11\x3a\x46\x9a\xfd\x9e\x75\x6f\x64\x92\x08\xd2\x94\x2f\xeb\xff\xb2\x2e\x83\x22\x79\x06\x3e\xc5\xb5\x7a\xb5\x42\xd9\xbb\xc5\x6e\x82\xcd\xc6\xa0\x3b\x00\xd1\x0d\x45\x80\x15\x75\xe9\x49\xe1"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x20\x71\x02\xf5\x98\xec\x28\x00\x45\xbe\x67\x59\x2f\x5b\xba\x25\xba\x2e\x2b\x56\xe0\xd2\x39\x7c\xbe\x85\x7c\xde\x52\xda\x8c\xca\x83\xae\x1e\x29\x61\x5c\x70\x56\xaf\x35\xe8\x31\x9f\x2a\xf8\x6f\xdc\xcc\x44\x34\xcd\x77\x07\xe3\x19\xc9\xb2\x35\x66\x59\xd7\x88\x67\xa6\x46\x7a\x15\x4e\x76\xb7\x3c\x81\x26\x0f\x3a\xb4\x43\xcc\x03\x9a\x0d\x42\x69\x50\x76\xa7\x9b\xd8\xca\x25\xeb\xc8\x95\x2e\xd4\x43\xc2\x10\x3b\x29\x00\xc9\xf5\x8b\x6a\x1c\x8a\x62\x66\xe4\x38\x80\xcd\xa9\x3b\xc6\x4d\x71\x4c\x98\x0c\xd8\x68\x8e\x8e\x63"[..];
            let expected = &b"\x77\xf0\xf2\xa0\x48\x48\xfe\x90\xa8\xeb\x35\xab\x5d\x94\xca\xe8\x43\xdb\x61\x02\x4d\x01\x67\x28\x9e\xea\x92\xe5\xd1\xe1\x0a\x52\x6e\x42\x0f\x2d\x33\x4f\x1b\xf2\xaa\x7e\xa4\xe1\x4a\x93\xa6\x8d\xba\x60\xfd\x2e\xde\x58\xb7\x94\xdc\xbd\x37\xdc\xb1\x96\x78\x77\xd6\xb6\x7d\xa3\xfd\xf2\xc0\xc7\x43\x3e\x47\x13\x4d\xde\x00\xc9\xc4\xd4\x07\x2e\x43\x36\x1a\x76\x7a\x52\x76\x75\xd8\xbd\xa7\xd5\x92\x1b\xd4\x83\xc9\x55\x19\x50\x73\x9e\x9b\x2b\xe0\x27\xdf\x30\x15\xb6\x1f\x75\x1a\xc1\xd9\xf3\x7b\xea\x32\x14\xd3\xc8\xdc\x96"[..];
            let mut hsh = Sha1::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x64\x4a\x3d\xe6\x10\x0d\xd8\xa3\x6c\x84\x14\x46\xb9\x37\x6b\x34\x5d\x47\x8a\x32\x94\x50\xa6\x6f\x62\x93\x13\xc5\xcc\x55\x13\x3c\x47\x82\xec\xd0\x71\x96\x3d\x74\xff\xbd\x91\x56\xf6\x39\x35\x65\x1f\x05\x47\x11\xb4\xb8\x10\x51\x60\xab\x94\xeb\x67\x5e\x66\xf0\x20\x18\xc1\x85\xac\xce\xd5\xe9\xe2\x46\x5f\xb4\x89\x7d\x7c\x5d\xca\x45\xbf\xff\xe4\x32\x81\x5d\x22\xb7\x78\x23\x0b\x8d\x8c\x6f\xd8\x54\xe5\x8f\x2b\x7d\x49\x0d\xfd\x67\xa5\xe8\xd8\xc8\xe9\x25\x47\x4f\x19\x86\x8c\x88\xa1\x9a\x90\xff\xea\xf6\x20\xa8\x2a\xc1"[..];
            let expected = &b"\x48\x11\x57\xd6\x5c\x91\xa0\x9b\x87\x1b\xc9\xf7\x04\xac\x2c\x31\xb1\xe6\xb0\x97\xe0\xd4\x9e\x29\x1e\x03\x7c\x11\xe7\x07\xf4\x8a\xc1\x66\x55\x8e\x9e\x8c\x11\x4e\xe4\x44\xc4\xd6\x49\xe7\xe2\xcf\x73\x74\x26\x9b\x03\x6f\xea\x99\xbb\x35\x66\xd1\x34\xd7\xae\x5d\xd4\x14\x1f\x73\x26\x88\x47\x46\xd3\x96\xbe\x32\x07\xda\x2d\x9f\x56\x86\x25\x85\x99\x3d\xb4\x2c\xe2\x82\xaa\x2f\x04\x8d\x12\xbc\xcf\xf1\x2f\x14\xb9\xd1\xac\x4e\x33\xd3\x71\xfd\x4c\x0d\xe1\x56\x3c\x97\x88\x26\x46\x8e\x6a\x37\x99\xf6\x4d\x39\x85\xd4\x68\x9e"[..];
            let mut hsh = Sha224::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x46\x7e\x8e\xa6\x34\xf7\x99\x5d\xc4\x6c\x11\xb8\xab\x0b\x75\x08\x89\x46\x81\xe8\x1c\x35\x02\xc3\xb3\x35\xe8\x97\xe6\xd6\x9d\xf8\x85\xf4\x95\x57\xce\x23\x27\x84\xe3\x51\x9b\x72\x7b\xa6\x84\x3b\xd7\xaf\x50\x63\xf8\xbc\x1d\x61\x0f\x86\xce\x5b\x35\x15\x5e\x32\x5c\xe1\x75\xbe\x85\x38\x39\x5b\x34\xdf\x67\xa4\x21\xfc\xa2\x7e\x31\x33\x0b\x59\xa4\x10\x11\xb2\x90\xa5\x8b\xdc\x8e\x74\x04\x01\xb3\x8f\x55\x64\xc2\xfd\x7a\xe8\x9f\x60\x9e\xd6\x07\xd5\x78\xdb\x7f\x1c\xda\x50\x8a\xf9\x87\xbe\x1f\xd9\x46\xa2\x5a\xb9\x34\x6d"[..];
            let expected = &b"\x2b\x1f\xfb\x37\x0d\x51\x8a\x82\x64\x6d\x86\x82\x8d\xb1\xfc\x7e\x8b\xfe\x73\xee\x87\x8d\xa1\x20\xfa\x92\x73\x7c\x91\x74\x68\x89\x95\xf2\x25\x5b\x29\xe8\x3b\x28\xc2\x44\xcc\x56\x3c\x9b\x33\xef\xd3\xf9\xf9\xe1\x63\x8e\x2c\x16\xe2\x4f\x2e\xae\x19\x43\x56\x96\xb2\xf4\xd1\xcf\x73\x06\x4f\xc1\xcf\xcc\xb2\x27\x8c\x01\xf0\x97\x9e\x7d\xe7\x46\x3b\xf8\x41\x7b\xd6\x98\x6f\xbf\x1d\x34\xd3\x82\xa9\x78\xce\x79\x95\x82\x44\x2a\xfc\xc9\x2b\x4f\xe7\x43\x21\x6b\x6f\x15\x1f\x6a\x56\x1d\x97\x9c\xf6\x83\xca\xb6\xaf\x2f\xf4\xc5"[..];
            let mut hsh = Sha256::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x46\x7e\x8e\xa6\x34\xf7\x99\x5d\xc4\x6c\x11\xb8\xab\x0b\x75\x08\x89\x46\x81\xe8\x1c\x35\x02\xc3\xb3\x35\xe8\x97\xe6\xd6\x9d\xf8\x85\xf4\x95\x57\xce\x23\x27\x84\xe3\x51\x9b\x72\x7b\xa6\x84\x3b\xd7\xaf\x50\x63\xf8\xbc\x1d\x61\x0f\x86\xce\x5b\x35\x15\x5e\x32\x5c\xe1\x75\xbe\x85\x38\x39\x5b\x34\xdf\x67\xa4\x21\xfc\xa2\x7e\x31\x33\x0b\x59\xa4\x10\x11\xb2\x90\xa5\x8b\xdc\x8e\x74\x04\x01\xb3\x8f\x55\x64\xc2\xfd\x7a\xe8\x9f\x60\x9e\xd6\x07\xd5\x78\xdb\x7f\x1c\xda\x50\x8a\xf9\x87\xbe\x1f\xd9\x46\xa2\x5a\xb9\x34\x6d"[..];
            let expected = &b"\xc7\x00\x28\x35\x57\xda\xfd\x1f\x88\x34\xec\x0b\x7a\x7e\xc7\x33\x71\x9c\xb0\xbe\x6e\xdb\x19\xf1\x06\x4e\xe9\x4c\x75\xb8\xd9\xd4\x94\x58\xfa\x18\x4f\x7d\x6d\xfa\x5a\x6d\xa2\xd2\xeb\xee\xf0\x65\x0d\x8a\xf3\x54\x47\x82\x3c\x83\xa7\x73\x78\x24\x50\x9a\x74\x25\x33\x9c\xaf\x99\x10\x1c\xd1\xfe\x3d\xb8\x83\xfb\x98\xd1\x72\x12\x7e\x30\xe3\x8d\x1d\x6f\x9e\x36\x54\x93\x7c\xd6\x8c\xbb\x4e\xa2\x28\xc8\x16\x06\x4f\xa8\xca\x09\x50\xc7\xe7\xb6\xad\x25\x04\x55\x74\xa6\xa4\x06\x3b\x63\xf0\x74\x66\xb2\xcb\x5d\x73\x11\xb7\xcf"[..];
            let mut hsh = Sha384::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }

        {
            let m = &b"\x46\x7e\x8e\xa6\x34\xf7\x99\x5d\xc4\x6c\x11\xb8\xab\x0b\x75\x08\x89\x46\x81\xe8\x1c\x35\x02\xc3\xb3\x35\xe8\x97\xe6\xd6\x9d\xf8\x85\xf4\x95\x57\xce\x23\x27\x84\xe3\x51\x9b\x72\x7b\xa6\x84\x3b\xd7\xaf\x50\x63\xf8\xbc\x1d\x61\x0f\x86\xce\x5b\x35\x15\x5e\x32\x5c\xe1\x75\xbe\x85\x38\x39\x5b\x34\xdf\x67\xa4\x21\xfc\xa2\x7e\x31\x33\x0b\x59\xa4\x10\x11\xb2\x90\xa5\x8b\xdc\x8e\x74\x04\x01\xb3\x8f\x55\x64\xc2\xfd\x7a\xe8\x9f\x60\x9e\xd6\x07\xd5\x78\xdb\x7f\x1c\xda\x50\x8a\xf9\x87\xbe\x1f\xd9\x46\xa2\x5a\xb9\x34\x6d"[..];
            let expected = &b"\x5d\x5c\xf1\x80\xbd\xac\x8a\xe1\x4a\x50\xc4\xe8\xb5\x7b\x88\xba\x68\xb1\xc3\x52\x7d\x34\xa6\x3f\xd3\x90\xf3\x3b\x8b\x02\x5a\x75\xf7\xce\x82\x4f\x1e\x20\xde\x81\x49\x91\x36\x4a\x97\xc2\xab\x9e\x6c\x88\xcd\x19\x6a\xbf\x6c\x4a\x0a\xc6\x60\x13\xa7\x3d\xb9\xe9\x4a\x98\x8a\x46\x65\xa3\x1c\xd4\xe0\x73\x18\x08\xc8\x8e\xc1\x45\x7c\x48\x10\x47\xf3\xe3\x2b\x08\xbf\xf6\x56\x0c\xbe\x85\xce\xc2\x12\x23\x9d\xc8\xb2\x54\x67\xde\xbe\x53\x6a\x8a\xb1\xa9\x51\xaf\xcd\xcb\x2c\xfc\x41\x1a\xfd\x5c\x18\x9f\x4b\x0e\xab\xee\xc3\xf7"[..];
            let mut hsh = Sha512::default();
            let mut sig = vec![0u8; 1024 / 8];

            hsh.update(m);
            assert!(sign_pkcs1(
                &public, &private, &mut hsh, &mut rnd, &mut sig
            )
            .is_ok());
            assert_eq!(sig, expected);
            hsh.update(m);
            assert_eq!(
                verify_pkcs1(&public, &mut hsh, expected).ok(),
                Some(true)
            );
        }
    }

    #[test]
    fn rsa_pkcs15_encrypt() {
        let mut rnd = Yarrow::default();
        let n = &b"\xc8\xa2\x06\x91\x82\x39\x4a\x2a\xb7\xc3\xf4\x19\x0c\x15\x58\x9c\x56\xa2\xd4\xbc\x42\xdc\xa6\x75\xb3\x4c\xc9\x50\xe2\x46\x63\x04\x84\x41\xe8\xaa\x59\x3b\x2b\xc5\x9e\x19\x8b\x8c\x25\x7e\x88\x21\x20\xc6\x23\x36\xe5\xcc\x74\x50\x12\xc7\xff\xb0\x63\xee\xbe\x53\xf3\xc6\x50\x4c\xba\x6c\xfe\x51\xba\xa3\xb6\xd1\x07\x4b\x2f\x39\x81\x71\xf4\xb1\x98\x2f\x4d\x65\xca\xf8\x82\xea\x4d\x56\xf3\x2a\xb5\x7d\x0c\x44\xe6\xad\x4e\x9c\xf5\x7a\x43\x39\xeb\x69\x62\x40\x6e\x35\x0c\x1b\x15\x39\x71\x83\xfb\xf1\xf0\x35\x3c\x9f\xc9\x91"[..];
        let e = &b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01"[..];
        let d = &b"\x5d\xfc\xb1\x11\x07\x2d\x29\x56\x5b\xa1\xdb\x3e\xc4\x8f\x57\x64\x5d\x9d\x88\x04\xed\x59\x8a\x4d\x47\x02\x68\xa8\x90\x67\xa2\xc9\x21\xdf\xf2\x4b\xa2\xe3\x7a\x3c\xe8\x34\x55\x50\x00\xdc\x86\x8e\xe6\x58\x8b\x74\x93\x30\x35\x28\xb1\xb3\xa9\x4f\x0b\x71\x73\x0c\xf1\xe8\x6f\xca\x5a\xee\xdc\x3a\xfa\x16\xf6\x5c\x01\x89\xd8\x10\xdd\xcd\x81\x04\x9e\xbb\xd0\x39\x18\x68\xc5\x0e\xde\xc9\x58\xb3\xa2\xaa\xef\xf6\xa5\x75\x89\x7e\x2f\x20\xa3\xab\x54\x55\xc1\xbf\xa5\x50\x10\xac\x51\xa7\x79\x9b\x1f\xf8\x48\x36\x44\xa3\xd4\x25"[..];
        let p = &b"\xd0\x6f\xfa\x56\x3b\xd0\xb8\xb9\x7f\x00\x72\xea\x07\x51\x03\xec\x1f\xf0\xb1\x7f\xd6\xbd\xaf\x94\xa7\x5a\xe6\x03\x59\x82\xf6\x80\x24\x9d\x77\xcc\x15\x96\xa6\x54\xf1\x4c\x51\x7a\x13\xb9\x5f\x1a\x8c\x5d\xe8\xcc\x84\xad\x38\xd2\xe6\xaa\x4f\xcd\x54\x1a\x32\xeb"[..];
        let q = &b"\xf6\x6a\x24\x68\xb1\x48\x1a\x0d\x6b\x60\x49\x67\xf0\x58\x03\x89\xd6\x06\x1f\x03\x3a\x9b\x57\xb7\x4d\x1b\xef\xe8\x10\x11\x98\x94\x5b\x80\x93\x04\x24\x1d\x02\xfd\x5f\x92\x1f\xe9\x59\xfb\xec\xdb\x18\x00\x54\x86\x9a\xdb\x17\xd3\x21\xf9\xd5\xd5\x98\x12\x3e\x73"[..];
        let public = PublicKey::new(n, e).unwrap();
        let private = PrivateKey::new(d, p, q, None).unwrap();

        {
            let m = &b"Hello, World"[..];
            let mut c = vec![0u8; 1024 / 8];

            assert!(encrypt_pkcs1(&public, &mut rnd, m, &mut c).is_ok());

            let m2 = decrypt_pkcs1_insecure(&public, &private, &mut rnd, &c)
                .unwrap();
            assert_eq!(m, &m2[..]);

            let mut m3 = vec![0; m.len()];
            decrypt_pkcs1(&public, &private, &mut rnd, &c, &mut m3)
                .unwrap();
            assert_eq!(m, &m3[..]);
        }
    }
}
