rc_crypto/digest.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5// This file contains code that was copied from the ring crate which is under
6// the ISC license, reproduced below:
7
8// Copyright 2015-2017 Brian Smith.
9
10// Permission to use, copy, modify, and/or distribute this software for any
11// purpose with or without fee is hereby granted, provided that the above
12// copyright notice and this permission notice appear in all copies.
13
14// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
15// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
17// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
22use crate::error::*;
23
24pub use nss::pk11::context::HashAlgorithm::{self as Algorithm, *};
25
26/// A calculated digest value.
27#[derive(Clone)]
28pub struct Digest {
29 pub(crate) value: Vec<u8>,
30 pub(crate) algorithm: Algorithm,
31}
32
33impl Digest {
34 pub fn algorithm(&self) -> &Algorithm {
35 &self.algorithm
36 }
37}
38
39impl AsRef<[u8]> for Digest {
40 fn as_ref(&self) -> &[u8] {
41 self.value.as_ref()
42 }
43}
44
45/// Returns the digest of data using the given digest algorithm.
46pub fn digest(algorithm: &Algorithm, data: &[u8]) -> Result<Digest> {
47 let value = nss::pk11::context::hash_buf(algorithm, data)?;
48 Ok(Digest {
49 value,
50 algorithm: *algorithm,
51 })
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 const MESSAGE: &[u8] = b"bobo";
59 const DIGEST_HEX: &str = "bf0c97708b849de696e7373508b13c5ea92bafa972fc941d694443e494a4b84d";
60
61 #[test]
62 fn sha256_digest() {
63 nss::ensure_initialized();
64 assert_eq!(hex::encode(digest(&SHA256, MESSAGE).unwrap()), DIGEST_HEX);
65 assert_ne!(
66 hex::encode(digest(&SHA256, b"notbobo").unwrap()),
67 DIGEST_HEX
68 );
69 }
70
71 #[test]
72 fn digest_cleanly_rejects_gigantic_messages() {
73 nss::ensure_initialized();
74 let message = vec![0; (i32::MAX as usize) + 1];
75 assert!(digest(&SHA256, &message).is_err());
76 }
77}