1#![doc = include_str!("../README.md")]
3mod constants;
4use blake2::Digest;
5use std::io::Read;
6
7use constants::*;
8mod errors;
9pub use errors::*;
10pub use public_key::PublicKeyBox;
11use public_key::{PublicKey, RawPk};
12pub use secret_key::SecretKeyBox;
13use signature::Signature;
14mod keypair;
15pub use keypair::KeyPairBox;
16mod public_key;
17mod secret_key;
18mod signature;
19pub use signature::SignatureBox;
20
21use crate::public_key::verify_prehashed;
22mod util;
23fn prehash<R>(data_reader: &mut R) -> Result<Vec<u8>>
24where
25 R: Read,
26{
27 let mut hash = blake2::Blake2b512::new();
28 let mut buf = [0; 2048];
29 loop {
30 let n = data_reader.read(&mut buf)?;
31 if n == 0 {
32 break;
33 }
34 hash.update(&buf[..n]);
35 }
36 Ok(hash.finalize().to_vec())
37}
38pub fn pub_key_from_str(s: &str) -> Result<PublicKeyBox<'_>> {
40 PublicKeyBox::from_str(s)
41}
42pub fn sec_key_from_str(s: &str) -> Result<SecretKeyBox<'_>> {
44 SecretKeyBox::from_str(s)
45}
46pub fn pub_key_from_sec_key<'s>(
50 sec_key: &SecretKeyBox<'s>,
51 password: Option<&[u8]>,
52) -> Result<PublicKeyBox<'s>> {
53 let keynum_sk = sec_key.xor_keynum_sk(password)?;
54 let pk_box = PublicKeyBox::new(
55 None,
56 PublicKey::new(
57 sec_key.sig_alg(),
58 keynum_sk.key_id,
59 RawPk(keynum_sk.pub_key),
60 ),
61 );
62 Ok(pk_box)
63}
64
65pub fn sign<'a, R>(
80 pk: Option<&PublicKeyBox>,
81 sk: &SecretKeyBox,
82 password: Option<&[u8]>,
83 mut data_reader: R,
84 trusted_comment: Option<&'a str>,
85 untrusted_comment: Option<&'a str>,
86) -> Result<SignatureBox<'a>>
87where
88 R: Read,
89{
90 let prehashed = prehash(&mut data_reader)?;
91 let sig = sk.sign(&prehashed, password)?;
92 let mut global_data = sig.to_bytes().to_vec();
93 global_data.extend_from_slice(trusted_comment.unwrap_or("").as_bytes());
94 let global_sig = sk.sign(&global_data, password)?;
95 let keynum_sk = sk.xor_keynum_sk(password)?;
96 let signature = Signature::new(SIGALG_PREHASHED, keynum_sk.key_id, sig, global_sig);
97 let sig_box = SignatureBox::new(untrusted_comment, trusted_comment, signature);
98 if let Some(pk) = pk {
99 verify_prehashed(pk, &sig_box, &prehashed)?;
100 }
101 Ok(sig_box)
102}
103pub fn verify<R>(
115 pk: &PublicKeyBox,
116 signature_box: &SignatureBox,
117 mut data_reader: R,
118) -> Result<bool>
119where
120 R: Read,
121{
122 let prehashed = prehash(&mut data_reader)?;
123 verify_prehashed(pk, signature_box, &prehashed)
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 #[test]
130 fn test() {
131 let KeyPairBox {
132 public_key_box,
133 secret_key_box,
134 } = KeyPairBox::generate(
135 Some(b"password"),
136 Some("pk untrusted comment"),
137 Some("sk untrusted comment"),
138 )
139 .unwrap();
140 let msg = "test";
141 let sig_box = sign(
142 Some(&public_key_box),
143 &secret_key_box,
144 Some(b"password"),
145 msg.as_bytes(),
146 Some("trusted comment"),
147 Some("untrusted comment"),
148 )
149 .unwrap();
150 let v = verify(&public_key_box, &sig_box, msg.as_bytes()).unwrap();
151 assert_eq!(v, true);
152 }
153}