summaryrefslogtreecommitdiffstats
path: root/openpgp/src/parse
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2022-12-11 09:57:00 +0100
committerNeal H. Walfield <neal@pep.foundation>2022-12-12 15:00:21 +0100
commit04d3c5ba245929530b8e2666509fa95df82c77bc (patch)
tree19907e127afa917d82e3c32cea71c8e91b9c3aac /openpgp/src/parse
parent43e8494d3576586c2f372c0f1b492ae5bca22ade (diff)
openpgp: Make hash_update_text more idomatic.
- Make `hash_update_text` a method on `HashingMode<Digest>`, `HashingMode<Digest>::update`.
Diffstat (limited to 'openpgp/src/parse')
-rw-r--r--openpgp/src/parse/hashed_reader.rs130
1 files changed, 68 insertions, 62 deletions
diff --git a/openpgp/src/parse/hashed_reader.rs b/openpgp/src/parse/hashed_reader.rs
index 1a02f079..3ac13b2b 100644
--- a/openpgp/src/parse/hashed_reader.rs
+++ b/openpgp/src/parse/hashed_reader.rs
@@ -6,8 +6,9 @@ use std::fmt;
use buffered_reader::BufferedReader;
use buffered_reader::buffered_reader_generic_read_impl;
-use crate::Result;
+use crate::crypto::hash::Digest;
use crate::parse::{Cookie, HashesFor, Hashing};
+use crate::Result;
use crate::types::HashAlgorithm;
use crate::types::SignatureType;
@@ -83,6 +84,53 @@ impl<T> HashingMode<T> {
HashingMode::Binary(t)
}
}
+
+ pub(crate) fn into_inner(self) -> T {
+ use self::HashingMode::*;
+ match self {
+ Binary(t) => t,
+ Text(t) => t,
+ }
+ }
+}
+
+impl<D> HashingMode<D>
+ where D: Digest
+{
+ /// Updates the given hash context. When in text mode, normalize
+ /// the line endings to "\r\n" on the fly.
+ pub(crate) fn update(&mut self, data: &[u8]) {
+ match self {
+ HashingMode::Text(h) => {
+ let mut line = data;
+ while ! line.is_empty() {
+ let mut next = 0;
+ for (i, c) in line.iter().cloned().enumerate() {
+ match c {
+ b'\r' | b'\n' => {
+ h.update(&line[..i]);
+ h.update(b"\r\n");
+ next = i + 1;
+ if c == b'\r' && line.get(next) == Some(&b'\n') {
+ next += 1;
+ }
+ break;
+ },
+ _ => (),
+ }
+ }
+
+ if next > 0 {
+ line = &line[next..];
+ } else {
+ h.update(line);
+ break;
+ }
+ }
+ }
+ HashingMode::Binary(h) => h.update(data),
+ }
+ }
}
pub(crate) struct HashedReader<R: BufferedReader<Cookie>> {
@@ -126,37 +174,6 @@ impl<R: BufferedReader<Cookie>> HashedReader<R> {
}
}
-/// Updates the given hash context normalizing line endings to "\r\n"
-/// on the fly.
-pub(crate) fn hash_update_text(h: &mut dyn crate::crypto::hash::Digest,
- text: &[u8]) {
- let mut line = text;
- while ! line.is_empty() {
- let mut next = 0;
- for (i, c) in line.iter().cloned().enumerate() {
- match c {
- b'\r' | b'\n' => {
- h.update(&line[..i]);
- h.update(b"\r\n");
- next = i + 1;
- if c == b'\r' && line.get(next) == Some(&b'\n') {
- next += 1;
- }
- break;
- },
- _ => (),
- }
- }
-
- if next > 0 {
- line = &line[next..];
- } else {
- h.update(line);
- break;
- }
- }
-}
-
impl Cookie {
fn hash_update(&mut self, data: &[u8]) {
let level = self.level.unwrap_or(0);
@@ -181,16 +198,13 @@ impl Cookie {
// We fix that here by hashing the stashed data into the
// former topmost signature-group's hash.
assert!(ngroups > 1);
- for mode in self.sig_groups[ngroups-2].hashes.iter_mut()
+ for h in self.sig_groups[ngroups-2].hashes.iter_mut()
{
t!("({:?}): group {} {:?} hashing {} stashed bytes.",
- hashes_for, ngroups-2, mode.map(|ctx| ctx.algo()),
+ hashes_for, ngroups-2, h.map(|ctx| ctx.algo()),
data.len());
- match mode {
- HashingMode::Binary(h) => h.update(&stashed_data),
- HashingMode::Text(h) => hash_update_text(h, &stashed_data),
- }
+ h.update(&stashed_data);
}
}
@@ -213,13 +227,10 @@ impl Cookie {
return;
}
- for mode in sig_group.hashes.iter_mut() {
+ for h in sig_group.hashes.iter_mut() {
t!("{:?}: group {} {:?} hashing {} bytes.",
- hashes_for, i, mode.map(|ctx| ctx.algo()), data.len());
- match mode {
- HashingMode::Binary(h) => h.update(data),
- HashingMode::Text(h) => hash_update_text(h, data),
- }
+ hashes_for, i, h.map(|ctx| ctx.algo()), data.len());
+ h.update(data);
}
}
}
@@ -261,17 +272,13 @@ impl Cookie {
// Hash stashed data first.
if let Some(stashed_data) = self.hash_stash.take() {
- for mode in self.sig_groups[0].hashes.iter_mut() {
+ for h in self.sig_groups[0].hashes.iter_mut() {
t!("{:?}: {:?} hashing {} stashed bytes.",
- hashes_for, mode.map(|ctx| ctx.algo()),
+ hashes_for, h.map(|ctx| ctx.algo()),
stashed_data.len());
- match mode {
- HashingMode::Binary(_) =>
- unreachable!("CSF transformation uses \
- text signatures"),
- HashingMode::Text(h) =>
- hash_update_text(h, &stashed_data[..]),
- }
+ assert!(matches!(h, HashingMode::Text(_)),
+ "CSF transformation uses text signatures");
+ h.update(&stashed_data[..]);
}
}
@@ -291,14 +298,12 @@ impl Cookie {
};
// Hash everything but the last newline now.
- for mode in self.sig_groups[0].hashes.iter_mut() {
+ for h in self.sig_groups[0].hashes.iter_mut() {
t!("{:?}: {:?} hashing {} bytes.",
- hashes_for, mode.map(|ctx| ctx.algo()), l);
- match mode {
- HashingMode::Binary(_) =>
- unreachable!("CSF transformation uses text signatures"),
- HashingMode::Text(h) => hash_update_text(h, &data[..l]),
- }
+ hashes_for, h.map(|ctx| ctx.algo()), l);
+ assert!(matches!(h, HashingMode::Text(_)),
+ "CSF transformation uses text signatures");
+ h.update(&data[..l]);
}
// The newline we stash away. If more text is written
@@ -522,8 +527,9 @@ mod test {
"one\rtwo\rthree",
"one\ntwo\r\nthree",
] {
- let mut ctx = HashAlgorithm::SHA256.context()?;
- super::hash_update_text(&mut ctx, text.as_bytes());
+ let mut ctx = HashingMode::Text(HashAlgorithm::SHA256.context()?);
+ ctx.update(text.as_bytes());
+ let mut ctx = ctx.into_inner();
let mut digest = vec![0; ctx.digest_size()];
let _ = ctx.digest(&mut digest);
assert_eq!(