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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::collections::HashSet;
use std::io;
use std::io::BufRead;
use std::io::Read;
use std::io::Write;
use failure::bail;
use failure::ensure;
use failure::err_msg;
use failure::format_err;
use failure::Error;
use crate::keyring::Keyring;
use crate::packets::SignatureType;
pub fn verify_message<R: BufRead, W: Write>(
from: R,
to: W,
keyring: &Keyring,
) -> Result<(), Error> {
let doc = crate::read_doc(from, io::BufWriter::new(to))?;
let body = doc
.body
.ok_or_else(|| err_msg("document wasn't a message (i.e. there was no body)"))?;
let signatures_of_correct_type: Vec<_> = doc
.signatures
.into_iter()
.filter(|sig| body.sig_type == sig.sig_type)
.collect();
ensure!(
!signatures_of_correct_type.is_empty(),
"no signatures are of the correct type"
);
crate::any_signature_valid(keyring, &signatures_of_correct_type, &body.digest)
.map_err(|errors| format_err!("no valid signatures: {:?}", errors))
}
pub fn verify_detached<S: BufRead, M: Read>(
signature: S,
mut message: M,
keyring: &Keyring,
) -> Result<(), Error> {
let doc = crate::read_doc(signature, iowrap::Ignore::new())?;
if doc.body.is_some() {
bail!("detached signature was a message");
}
let signatures = doc.signatures;
let mut body_modes = HashSet::with_capacity(4);
if signatures.is_empty() {
bail!("no signatures in signature file")
}
for sig in &signatures {
body_modes.insert((sig.sig_type, sig.hash_alg));
}
let (sig_type, hash_type) = *match body_modes.len() {
0 => unreachable!(),
1 => body_modes.iter().next().unwrap(),
_ => bail!(
"unsupported: signatures with multiple modes: {:?}",
body_modes
),
};
match sig_type {
SignatureType::Binary => (),
other => bail!("unsupported: detached signature of type: {:?}", other),
}
let mut digest = crate::load::digestable_for(hash_type)
.ok_or_else(|| format_err!("unsuported: hash type {:?}", hash_type))?;
let mut buf = [0u8; 8 * 1024];
loop {
let read = message.read(&mut buf)?;
if 0 == read {
break;
}
let buf = &buf[..read];
digest.process(buf);
}
crate::any_signature_valid(keyring, &signatures, &digest)
.map_err(|errors| format_err!("no valid signatures: {:?}", errors))
}