summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2021-11-05 14:58:19 +0100
committerJustus Winter <justus@sequoia-pgp.org>2021-11-05 14:58:19 +0100
commitd768ed170e5e43ddae2b53632a7b9a7e39d8fd49 (patch)
treeaef7579ee5085eeb8fd36e1e22edb377c0b9de6b
parent3b7cd3bd1460cda86160d232653417741fea2c5d (diff)
openpgp: Move CRC computation to its own module.
-rw-r--r--openpgp/src/armor.rs62
-rw-r--r--openpgp/src/armor/crc.rs87
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
+ }
+ }
+}