1mod constants;
2use blake2::Digest;
3use std::io::Read;
4
5use constants::*;
6mod errors;
7pub use errors::*;
8pub use public_key::PublicKeyBox;
9use public_key::{PublicKey, RawPk};
10pub use secret_key::SecretKeyBox;
11use signature::Signature;
12mod keypair;
13pub use keypair::KeyPairBox;
14mod public_key;
15mod secret_key;
16mod signature;
17pub use signature::SignatureBox;
18mod util;
19fn prehash<R>(data_reader: &mut R) -> Result<Vec<u8>>
20where
21 R: Read,
22{
23 let mut hash = blake2::Blake2b512::new();
24 let mut buf = [0; 2048];
25 loop {
26 let n = data_reader.read(&mut buf)?;
27 if n == 0 {
28 break;
29 }
30 hash.update(&buf[..n]);
31 }
32 Ok(hash.finalize().to_vec())
33}
34pub fn pub_key_from_str(s: &str) -> Result<PublicKeyBox> {
36 PublicKeyBox::from_str(s)
37}
38pub fn sec_key_from_str(s: &str) -> Result<SecretKeyBox> {
40 SecretKeyBox::from_str(s)
41}
42pub fn pub_key_from_sec_key<'s>(
46 sec_key: &SecretKeyBox<'s>,
47 password: Option<&[u8]>,
48) -> Result<PublicKeyBox<'s>> {
49 let keynum_sk = sec_key.xor_keynum_sk(password)?;
50 let pk_box = PublicKeyBox::new(
51 None,
52 PublicKey::new(
53 sec_key.secret_key.sig_alg,
54 keynum_sk.key_id,
55 RawPk(keynum_sk.pub_key),
56 ),
57 );
58 Ok(pk_box)
59}
60pub fn sign<'a, R>(
75 pk: Option<&PublicKeyBox>,
76 sk: &SecretKeyBox,
77 password: Option<&[u8]>,
78 mut data_reader: R,
79 trusted_comment: Option<&'a str>,
80 untrusted_comment: Option<&'a str>,
81) -> Result<SignatureBox<'a>>
82where
83 R: Read,
84{
85 let prehashed = prehash(&mut data_reader)?;
86 let sig = sk.sign(&prehashed, password)?;
87 let mut global_data = sig.to_bytes().to_vec();
88 global_data.extend_from_slice(trusted_comment.unwrap_or("").as_bytes());
89 let global_sig = sk.sign(&global_data, password)?;
90 let keynum_sk = sk.xor_keynum_sk(password)?;
91 let signature = Signature::new(SIGALG_PREHASHED, keynum_sk.key_id, sig, global_sig);
92 let sig_box = SignatureBox::new(untrusted_comment, trusted_comment, signature);
93 if let Some(pk) = pk {
94 verify_prehashed(pk, &sig_box, &prehashed)?;
95 }
96 Ok(sig_box)
97}
98pub fn verify<R>(
110 pk: &PublicKeyBox,
111 signature_box: &SignatureBox,
112 mut data_reader: R,
113) -> Result<bool>
114where
115 R: Read,
116{
117 let prehashed = prehash(&mut data_reader)?;
118 verify_prehashed(pk, signature_box, &prehashed)
119}
120fn verify_prehashed(
121 pk: &PublicKeyBox,
122 signature_box: &SignatureBox,
123 prehashed: &[u8],
124) -> Result<bool> {
125 if !signature_box.is_prehashed() {
126 return Err(SError::new(
127 ErrorKind::PrehashedMismatch,
128 "SignatureBox is not prehashed",
129 ));
130 }
131 if !pk.self_verify()? {
132 return Err(SError::new(
133 ErrorKind::PublicKey,
134 "public key self verification failed",
135 ));
136 }
137 if pk.public_key.key_id != *signature_box.key_id() {
138 return Err(SError::new(
139 ErrorKind::PublicKey,
140 "public key key_id mismatch",
141 ));
142 }
143 pk.verify(
144 prehashed,
145 &signature_box.signature,
146 signature_box.trusted_comment(),
147 )
148}
149#[cfg(test)]
150mod tests {
151
152 use super::*;
153 #[test]
154 fn test() {
155 let KeyPairBox {
156 public_key_box,
157 secret_key_box,
158 } = KeyPairBox::generate(
159 Some(b"password"),
160 Some("pk untrusted comment"),
161 Some("sk untrusted comment"),
162 )
163 .unwrap();
164 let msg = "test";
165 let sig_box = sign(
166 Some(&public_key_box),
167 &secret_key_box,
168 Some(b"password"),
169 msg.as_bytes(),
170 Some("trusted comment"),
171 Some("untrusted comment"),
172 )
173 .unwrap();
174 let v = verify(&public_key_box, &sig_box, msg.as_bytes()).unwrap();
175 assert_eq!(v, true);
176 }
177}