瀏覽代碼

serial: Support variable-length BLAKE2b encoding.

parazyd 2 年之前
父節點
當前提交
856b026f6b
共有 3 個文件被更改,包括 89 次插入11 次删除
  1. 1 2
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 87 9
      src/serial/src/types/hash.rs

+ 1 - 2
Cargo.lock

@@ -612,8 +612,7 @@ dependencies = [
 [[package]]
 name = "blake2b_simd"
 version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc"
+source = "git+https://github.com/parazyd/blake2_simd?branch=impl-common#e430c2288f38379f9f24b704b19e1346033d6616"
 dependencies = [
  "arrayref",
  "arrayvec",

+ 1 - 0
Cargo.toml

@@ -301,3 +301,4 @@ halo2_proofs = {git="https://github.com/parazyd/halo2", branch="v4"}
 halo2_gadgets = {git="https://github.com/parazyd/halo2", branch="v4"}
 arti-client = {git="https://gitlab.torproject.org/tpo/core/arti", rev="3fdadcc7509f60cfdfc51df2664aaf2f73bbd2f0"}
 tor-hscrypto = {git="https://gitlab.torproject.org/tpo/core/arti", rev="3fdadcc7509f60cfdfc51df2664aaf2f73bbd2f0"}
+blake2b_simd = {git="https://github.com/parazyd/blake2_simd", branch="impl-common"}

+ 87 - 9
src/serial/src/types/hash.rs

@@ -16,7 +16,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::io::{Read, Result, Write};
+use std::io::{Error, ErrorKind, Read, Result, Write};
 
 #[cfg(feature = "async")]
 use crate::{
@@ -29,8 +29,17 @@ use crate::{Decodable, Encodable, ReadExt, WriteExt};
 #[cfg(feature = "blake2b_simd")]
 impl Encodable for blake2b_simd::Hash {
     fn encode<S: Write>(&self, mut s: S) -> Result<usize> {
+        // The hash can be of variable output length.
+        // We'll support 16, 32, and 64 bytes, otherwise panic.
+        // This means we need 1 byte to tell the length.
+        let len = self.as_bytes().len();
+        if len != 16 && len != 32 && len != 64 {
+            panic!("blake2b serialization supports only 16, 32, or 64 bytes");
+        }
+
+        s.write_u8(len as u8)?;
         s.write_slice(self.as_bytes())?;
-        Ok(blake2b_simd::OUTBYTES)
+        Ok(len + 1)
     }
 }
 
@@ -38,17 +47,40 @@ impl Encodable for blake2b_simd::Hash {
 #[async_trait]
 impl AsyncEncodable for blake2b_simd::Hash {
     async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> Result<usize> {
+        // The hash can be of variable output length.
+        // We'll support 32 and 64 bytes, otherwise panic.
+        // This means we need 1 byte to tell the length.
+        let len = self.as_bytes().len();
+        if len != 16 && len != 32 && len != 64 {
+            panic!("blake2b serialization supports only 16, 32, or 64 bytes");
+        }
+
+        s.write_u8_async(len as u8).await?;
         s.write_slice_async(self.as_bytes()).await?;
-        Ok(blake2b_simd::OUTBYTES)
+        Ok(len)
     }
 }
 
 #[cfg(feature = "blake2b_simd")]
 impl Decodable for blake2b_simd::Hash {
     fn decode<D: Read>(mut d: D) -> Result<Self> {
-        let mut bytes = [0u8; blake2b_simd::OUTBYTES];
-        d.read_slice(&mut bytes)?;
-        Ok(bytes.into())
+        let len = d.read_u8()?;
+
+        if len == 16 {
+            let mut bytes = [0u8; 16];
+            d.read_slice(&mut bytes)?;
+            Ok(blake2b_simd::Hash::from(bytes))
+        } else if len == 32 {
+            let mut bytes = [0u8; 32];
+            d.read_slice(&mut bytes)?;
+            Ok(blake2b_simd::Hash::from(bytes))
+        } else if len == 64 {
+            let mut bytes = [0u8; 64];
+            d.read_slice(&mut bytes)?;
+            Ok(blake2b_simd::Hash::from(bytes))
+        } else {
+            Err(Error::new(ErrorKind::Other, "Unsupported blake2b hash length"))
+        }
     }
 }
 
@@ -56,9 +88,23 @@ impl Decodable for blake2b_simd::Hash {
 #[async_trait]
 impl AsyncDecodable for blake2b_simd::Hash {
     async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> Result<Self> {
-        let mut bytes = [0u8; blake2b_simd::OUTBYTES];
-        d.read_slice_async(&mut bytes).await?;
-        Ok(bytes.into())
+        let len = d.read_u8_async().await?;
+
+        if len == 16 {
+            let mut bytes = [0u8; 16];
+            d.read_slice_async(&mut bytes).await?;
+            Ok(blake2b_simd::Hash::from(bytes))
+        } else if len == 32 {
+            let mut bytes = [0u8; 32];
+            d.read_slice_async(&mut bytes).await?;
+            Ok(blake2b_simd::Hash::from(bytes))
+        } else if len == 64 {
+            let mut bytes = [0u8; 64];
+            d.read_slice_async(&mut bytes).await?;
+            Ok(blake2b_simd::Hash::from(bytes))
+        } else {
+            Err(Error::new(ErrorKind::Other, "Unsupported blake2b hash length"))
+        }
     }
 }
 
@@ -97,3 +143,35 @@ impl AsyncDecodable for blake3::Hash {
         Ok(bytes.into())
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use crate::{deserialize, serialize};
+
+    #[test]
+    fn serialize_deserialize_blake2b() {
+        let hash16 =
+            blake2b_simd::Params::new().hash_length(16).to_state().update(b"foo").finalize();
+        let hash16_ser = serialize(&hash16);
+        assert!(hash16_ser.len() == 17);
+
+        let hash16_de: blake2b_simd::Hash = deserialize(&hash16_ser).unwrap();
+        assert!(hash16 == hash16_de);
+
+        let hash32 =
+            blake2b_simd::Params::new().hash_length(32).to_state().update(b"foo").finalize();
+        let hash32_ser = serialize(&hash32);
+        assert!(hash32_ser.len() == 33);
+
+        let hash32_de: blake2b_simd::Hash = deserialize(&hash32_ser).unwrap();
+        assert!(hash32 == hash32_de);
+
+        let hash64 =
+            blake2b_simd::Params::new().hash_length(64).to_state().update(b"foo").finalize();
+        let hash64_ser = serialize(&hash64);
+        assert!(hash64_ser.len() == 65);
+
+        let hash64_de: blake2b_simd::Hash = deserialize(&hash64_ser).unwrap();
+        assert!(hash64 == hash64_de);
+    }
+}