nuts_container/
digest.rs

1// MIT License
2//
3// Copyright (c) 2022-2024 Robin Doer
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to
7// deal in the Software without restriction, including without limitation the
8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9// sell copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21// IN THE SOFTWARE.
22
23#[cfg(test)]
24mod tests;
25
26use openssl::hash::MessageDigest;
27use std::fmt;
28use std::str::FromStr;
29
30use crate::buffer::{Buffer, BufferError, BufferMut};
31
32/// Supported message digests.
33#[derive(Clone, Copy, Debug, PartialEq)]
34pub enum Digest {
35    /// SHA1
36    Sha1,
37
38    /// SHA2 with a 224 bit hash
39    Sha224,
40
41    /// SHA2 with a 256 bit hash
42    Sha256,
43
44    /// SHA2 with a 384 bit hash
45    Sha384,
46
47    /// SHA2 with a 512 bit hash
48    Sha512,
49}
50
51impl fmt::Display for Digest {
52    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
53        let s = match self {
54            Digest::Sha1 => "sha1",
55            Digest::Sha224 => "sha224",
56            Digest::Sha256 => "sha256",
57            Digest::Sha384 => "sha384",
58            Digest::Sha512 => "sha512",
59        };
60
61        fmt.write_str(s)
62    }
63}
64
65impl FromStr for Digest {
66    type Err = ();
67
68    fn from_str(str: &str) -> Result<Self, ()> {
69        match str {
70            "sha1" => Ok(Digest::Sha1),
71            "sha224" => Ok(Digest::Sha224),
72            "sha256" => Ok(Digest::Sha256),
73            "sha384" => Ok(Digest::Sha384),
74            "sha512" => Ok(Digest::Sha512),
75            _ => Err(()),
76        }
77    }
78}
79
80impl Digest {
81    /// Return the size of the message digest.
82    ///
83    /// This is the size of the resulting hash.
84    pub fn size(&self) -> usize {
85        match self {
86            Digest::Sha1 => 20,
87            Digest::Sha224 => 28,
88            Digest::Sha256 => 32,
89            Digest::Sha384 => 48,
90            Digest::Sha512 => 64,
91        }
92    }
93
94    pub(crate) fn get_from_buffer<T: Buffer>(buf: &mut T) -> Result<Digest, BufferError> {
95        let b = buf.get_u32()?;
96
97        match b {
98            0 => Ok(Digest::Sha1),
99            1 => Ok(Digest::Sha224),
100            2 => Ok(Digest::Sha256),
101            3 => Ok(Digest::Sha384),
102            4 => Ok(Digest::Sha512),
103            _ => Err(BufferError::InvalidIndex("Digest".to_string(), b)),
104        }
105    }
106
107    pub(crate) fn put_into_buffer<T: BufferMut>(&self, buf: &mut T) -> Result<(), BufferError> {
108        let b = match self {
109            Digest::Sha1 => 0,
110            Digest::Sha224 => 1,
111            Digest::Sha256 => 2,
112            Digest::Sha384 => 3,
113            Digest::Sha512 => 4,
114        };
115
116        buf.put_u32(b)
117    }
118
119    pub(crate) fn as_openssl(&self) -> MessageDigest {
120        match self {
121            Digest::Sha1 => MessageDigest::sha1(),
122            Digest::Sha224 => MessageDigest::sha224(),
123            Digest::Sha256 => MessageDigest::sha256(),
124            Digest::Sha384 => MessageDigest::sha384(),
125            Digest::Sha512 => MessageDigest::sha512(),
126        }
127    }
128}