diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2021-11-05 14:58:19 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2021-11-05 14:58:19 +0100 |
commit | d768ed170e5e43ddae2b53632a7b9a7e39d8fd49 (patch) | |
tree | aef7579ee5085eeb8fd36e1e22edb377c0b9de6b /openpgp | |
parent | 3b7cd3bd1460cda86160d232653417741fea2c5d (diff) |
openpgp: Move CRC computation to its own module.
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/src/armor.rs | 62 | ||||
-rw-r--r-- | openpgp/src/armor/crc.rs | 87 |
2 files changed, 92 insertions, 57 deletions
diff --git a/openpgp/src/armor.rs b/openpgp/src/armor.rs index 443fe58c..968fe025 100644 --- a/openpgp/src/armor.rs +++ b/openpgp/src/armor.rs @@ -50,6 +50,8 @@ use crate::{vec_resize, vec_truncate}; mod base64_utils; use base64_utils::*; +mod crc; +use crc::CRC; /// The encoded output stream must be represented in lines of no more /// than 76 characters each (see (see [RFC 4880, section @@ -1725,40 +1727,6 @@ impl BufferedReader<Cookie> for Reader<'_> { } } -const CRC24_INIT: u32 = 0xB704CE; -const CRC24_POLY: u32 = 0x864CFB; - -#[derive(Debug)] -struct CRC { - n: u32, -} - -/// Computes the CRC-24, (see [RFC 4880, section 6.1]). -/// -/// [RFC 4880, section 6.1]: https://tools.ietf.org/html/rfc4880#section-6.1 -impl CRC { - fn new() -> Self { - CRC { n: CRC24_INIT } - } - - fn update(&mut self, buf: &[u8]) -> &Self { - for octet in buf { - self.n ^= (*octet as u32) << 16; - for _ in 0..8 { - self.n <<= 1; - if self.n & 0x1000000 > 0 { - self.n ^= CRC24_POLY; - } - } - } - self - } - - fn finalize(&self) -> u32 { - self.n & 0xFFFFFF - } -} - /// Returns all character from Unicode's "Dash Punctuation" category. fn dashes() -> impl Iterator<Item = char> { ['\u{002D}', // - (Hyphen-Minus) @@ -1839,31 +1807,9 @@ fn dash_prefix(d: &[u8]) -> (&[u8], &[u8]) { #[cfg(test)] mod test { use std::io::{Cursor, Read, Write}; - use super::CRC; use super::Kind; use super::Writer; - #[test] - fn crc() { - let b = b"foobarbaz"; - let crcs = [ - 0xb704ce, - 0x6d2804, - 0xa2d10d, - 0x4fc255, - 0x7aafca, - 0xc79c46, - 0x7334de, - 0x77dc72, - 0x000f65, - 0xf40d86, - ]; - - for len in 0..b.len() + 1 { - assert_eq!(CRC::new().update(&b[..len]).finalize(), crcs[len]); - } - } - macro_rules! t { ( $path: expr ) => { include_bytes!(concat!("../tests/data/armor/", $path)) @@ -1896,7 +1842,9 @@ mod test { #[test] fn enarmor() { - for (bin, asc) in TEST_BIN.iter().zip(TEST_ASC.iter()) { + for (i, (bin, asc)) in TEST_BIN.iter().zip(TEST_ASC.iter()).enumerate() + { + eprintln!("Test {}", i); let mut w = Writer::new(Vec::new(), Kind::File).unwrap(); w.write(&[]).unwrap(); // Avoid zero-length optimization. diff --git a/openpgp/src/armor/crc.rs b/openpgp/src/armor/crc.rs new file mode 100644 index 00000000..f9f695bd --- /dev/null +++ b/openpgp/src/armor/crc.rs @@ -0,0 +1,87 @@ +//! Computes the CRC-24, (see [RFC 4880, section 6.1]). +//! +//! [RFC 4880, section 6.1]: https://tools.ietf.org/html/rfc4880#section-6.1 + +const CRC24_INIT: u32 = 0xB704CE; +const CRC24_POLY: u32 = 0x864CFB; + +#[derive(Debug)] +pub struct CRC { + n: u32, +} + +/// Computes the CRC-24, (see [RFC 4880, section 6.1]). +/// +/// [RFC 4880, section 6.1]: https://tools.ietf.org/html/rfc4880#section-6.1 +impl CRC { + pub fn new() -> Self { + CRC { n: CRC24_INIT } + } + + pub fn update(&mut self, buf: &[u8]) -> &Self { + for octet in buf { + self.n ^= (*octet as u32) << 16; + for _ in 0..8 { + self.n <<= 1; + if self.n & 0x1000000 > 0 { + self.n ^= CRC24_POLY; + } + } + } + self + } + + pub fn finalize(&self) -> u32 { + self.n & 0xFFFFFF + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn foobarbaz() { + let b = b"foobarbaz"; + let crcs = [ + 0xb704ce, + 0x6d2804, + 0xa2d10d, + 0x4fc255, + 0x7aafca, + 0xc79c46, + 0x7334de, + 0x77dc72, + 0x000f65, + 0xf40d86, + ]; + + for len in 0..b.len() + 1 { + assert_eq!(CRC::new().update(&b[..len]).finalize(), crcs[len]); + } + } + + /// Reference implementation of the iterative CRC24 computation. + fn iterative(buf: &[u8]) -> u32 { + let mut n = CRC24_INIT; + for octet in buf { + n ^= (*octet as u32) << 16; + for _ in 0..8 { + n <<= 1; + if n & 0x1000000 > 0 { + n ^= CRC24_POLY; + } + } + } + n & 0xFFFFFF + } + + quickcheck! { + fn compare(b: Vec<u8>) -> bool { + let mut c = CRC::new(); + c.update(&b); + assert_eq!(c.finalize(), iterative(&b)); + true + } + } +} |