1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
mod local_prelude {
    pub use crate::{
        algo::{
            cipher::{aes256::ctr::Algo as AES256_CTR, symmetric as symm},
            hash::{
                asymmetric::{Algo as AsymmHashAlgo, KeyPair as AsymmHashKeyPair},
                rsa::pss_sha384_mgf1_65537::{Algo as RSA, KeyPair as RSAKey},
            },
            key_deriv::hkdf::sha384::Algo as HKDF_SHA384,
            Algo as A, Key as K, SafeGenerateKey,
        },
        encoding::base64::{decode_no_padding as b64_decode, encode_no_padding as b64_encode},
        token::paseto::{
            collapse_to_vec, multi_part_pre_auth_encoding, token,
            v1::{
                nonce::{Nonce, Randomness},
                public::{error::Error, HEADER},
            },
            KnownClaims,
        },
        BoolToResult,
    };
    pub use serde::{de::DeserializeOwned, Deserialize, Serialize};
    pub use serde_json as json;
    pub use std::{convert::TryFrom, ops::Deref, str};
}
use self::{decryption::VerifiedToken, encryption::SignedToken, local_prelude::*};

mod decryption;
mod encryption;
mod error;

pub const VERSION: &'static str = "v1";
pub const PURPOSE: &'static str = "public";
pub const HEADER: token::Header = token::Header::new(VERSION.as_bytes(), PURPOSE.as_bytes());

impl token::SerializedData {
    // TODO replace with when Error::FailedToSign when enum variants become types
    /// Error, if Err, is always FailedToSign
    fn v1_public_sign(self, key: &RSAKey) -> Result<SignedToken, Error> {
        SignedToken::try_from((self, key))
    }
}
impl token::Unpacked {
    fn v1_public_verify(self, key: &RSAKey) -> Result<VerifiedToken, Error> {
        self.verify_header(HEADER).ok_or(Error::Unpacking)?;
        VerifiedToken::try_from((self, key))
    }
}

pub fn encrypt<T, F>(
    tok: token::Data<T, F>,
    private_key: &RSAKey,
) -> Result<token::Packed, error::Error>
where
    T: Serialize,
    F: Serialize,
{
    Ok(tok
        .serialize()?
        .v1_public_sign(private_key)?
        .canonicalize()
        .pack())
}
pub fn decrypt<T, F>(
    tok: token::Packed,
    key: &RSAKey,
) -> Result<token::Data<T, F>, error::Error>
where
    T: DeserializeOwned,
    F: DeserializeOwned,
{
    Ok(tok
        .unpack()?
        .v1_public_verify(key)?
        .canonicalize()
        .deserialize()?)
}


#[cfg(test)]
mod unit_tests {
    use super::*;
    use crate::algo::SafeGenerateKey;

    #[test]
    fn v1_public_cycle() {
        let orig = token::Data {
            msg: "hello".to_owned(),
            footer: Some("weird thing".to_owned()),
        };
        let beginning = orig.clone();
        let key = RSAKey::generate(&()).unwrap();
        let encrypted_tok = encrypt(beginning, &key).unwrap();
        let decrypted_tok: token::Data<String, String> = decrypt(encrypted_tok, &key).unwrap();
        assert_eq!(orig, decrypted_tok);
    }
}