digest_tests.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. // Copyright 2015-2017 Brian Smith.
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
  8. // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
  10. // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. use ring::{digest, test, test_file};
  15. #[cfg(target_arch = "wasm32")]
  16. use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
  17. #[cfg(target_arch = "wasm32")]
  18. wasm_bindgen_test_configure!(run_in_browser);
  19. /// Test vectors from BoringSSL, Go, and other sources.
  20. #[test]
  21. #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
  22. fn digest_misc() {
  23. test::run(test_file!("digest_tests.txt"), |section, test_case| {
  24. assert_eq!(section, "");
  25. let digest_alg = test_case.consume_digest_alg("Hash").unwrap();
  26. let input = test_case.consume_bytes("Input");
  27. let repeat = test_case.consume_usize("Repeat");
  28. let expected = test_case.consume_bytes("Output");
  29. let mut ctx = digest::Context::new(digest_alg);
  30. let mut data = Vec::new();
  31. for _ in 0..repeat {
  32. ctx.update(&input);
  33. data.extend(&input);
  34. }
  35. let actual_from_chunks = ctx.finish();
  36. assert_eq!(&expected, &actual_from_chunks.as_ref());
  37. let actual_from_one_shot = digest::digest(digest_alg, &data);
  38. assert_eq!(&expected, &actual_from_one_shot.as_ref());
  39. Ok(())
  40. });
  41. }
  42. mod digest_shavs {
  43. use ring::{digest, test};
  44. fn run_known_answer_test(digest_alg: &'static digest::Algorithm, test_file: test::File) {
  45. let section_name = &format!("L = {}", digest_alg.output_len);
  46. test::run(test_file, |section, test_case| {
  47. assert_eq!(section_name, section);
  48. let len_bits = test_case.consume_usize("Len");
  49. let mut msg = test_case.consume_bytes("Msg");
  50. // The "msg" field contains the dummy value "00" when the
  51. // length is zero.
  52. if len_bits == 0 {
  53. assert_eq!(msg, &[0u8]);
  54. msg.truncate(0);
  55. }
  56. assert_eq!(msg.len() * 8, len_bits);
  57. let expected = test_case.consume_bytes("MD");
  58. let actual = digest::digest(digest_alg, &msg);
  59. assert_eq!(&expected, &actual.as_ref());
  60. Ok(())
  61. });
  62. }
  63. macro_rules! shavs_tests {
  64. ( $file_name:ident, $algorithm_name:ident ) => {
  65. #[allow(non_snake_case)]
  66. mod $algorithm_name {
  67. use super::{run_known_answer_test, run_monte_carlo_test};
  68. use ring::{digest, test_file};
  69. #[cfg(target_arch = "wasm32")]
  70. use wasm_bindgen_test::wasm_bindgen_test;
  71. #[test]
  72. #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
  73. fn short_msg_known_answer_test() {
  74. run_known_answer_test(
  75. &digest::$algorithm_name,
  76. test_file!(concat!(
  77. "../third_party/NIST/SHAVS/",
  78. stringify!($file_name),
  79. "ShortMsg.rsp"
  80. )),
  81. );
  82. }
  83. #[test]
  84. #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
  85. fn long_msg_known_answer_test() {
  86. run_known_answer_test(
  87. &digest::$algorithm_name,
  88. test_file!(concat!(
  89. "../third_party/NIST/SHAVS/",
  90. stringify!($file_name),
  91. "LongMsg.rsp"
  92. )),
  93. );
  94. }
  95. #[test]
  96. #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
  97. fn monte_carlo_test() {
  98. run_monte_carlo_test(
  99. &digest::$algorithm_name,
  100. test_file!(concat!(
  101. "../third_party/NIST/SHAVS/",
  102. stringify!($file_name),
  103. "Monte.rsp"
  104. )),
  105. );
  106. }
  107. }
  108. };
  109. }
  110. fn run_monte_carlo_test(digest_alg: &'static digest::Algorithm, test_file: test::File) {
  111. let section_name = &format!("L = {}", digest_alg.output_len);
  112. let mut expected_count: isize = -1;
  113. let mut seed = Vec::with_capacity(digest_alg.output_len);
  114. test::run(test_file, |section, test_case| {
  115. assert_eq!(section_name, section);
  116. if expected_count == -1 {
  117. seed.extend(test_case.consume_bytes("Seed"));
  118. expected_count = 0;
  119. return Ok(());
  120. }
  121. assert!(expected_count >= 0);
  122. let actual_count = test_case.consume_usize("COUNT");
  123. assert_eq!(expected_count as usize, actual_count);
  124. expected_count += 1;
  125. let expected_md = test_case.consume_bytes("MD");
  126. let mut mds = Vec::with_capacity(4);
  127. mds.push(seed.clone());
  128. mds.push(seed.clone());
  129. mds.push(seed.clone());
  130. for _ in 0..1000 {
  131. let mut ctx = digest::Context::new(digest_alg);
  132. ctx.update(&mds[0]);
  133. ctx.update(&mds[1]);
  134. ctx.update(&mds[2]);
  135. let md_i = ctx.finish();
  136. let _ = mds.remove(0);
  137. mds.push(Vec::from(md_i.as_ref()));
  138. }
  139. let md_j = mds.last().unwrap();
  140. assert_eq!(&expected_md, md_j);
  141. seed = md_j.clone();
  142. Ok(())
  143. });
  144. assert_eq!(expected_count, 100);
  145. }
  146. shavs_tests!(SHA1, SHA1_FOR_LEGACY_USE_ONLY);
  147. shavs_tests!(SHA256, SHA256);
  148. shavs_tests!(SHA384, SHA384);
  149. shavs_tests!(SHA512, SHA512);
  150. }
  151. /// Test some ways in which `Context::update` and/or `Context::finish`
  152. /// could go wrong by testing every combination of updating three inputs
  153. /// that vary from zero bytes to one byte larger than the block length.
  154. ///
  155. /// These are not run in dev (debug) builds because they are too slow.
  156. macro_rules! test_i_u_f {
  157. ( $test_name:ident, $alg:expr) => {
  158. #[cfg(not(debug_assertions))]
  159. // TODO: #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
  160. #[test]
  161. fn $test_name() {
  162. let mut input = [0; (digest::MAX_BLOCK_LEN + 1) * 3];
  163. let max = $alg.block_len + 1;
  164. for i in 0..(max * 3) {
  165. input[i] = (i & 0xff) as u8;
  166. }
  167. for i in 0..max {
  168. for j in 0..max {
  169. for k in 0..max {
  170. let part1 = &input[..i];
  171. let part2 = &input[i..(i + j)];
  172. let part3 = &input[(i + j)..(i + j + k)];
  173. let mut ctx = digest::Context::new(&$alg);
  174. ctx.update(part1);
  175. ctx.update(part2);
  176. ctx.update(part3);
  177. let i_u_f = ctx.finish();
  178. let one_shot = digest::digest(&$alg, &input[..(i + j + k)]);
  179. assert_eq!(i_u_f.as_ref(), one_shot.as_ref());
  180. }
  181. }
  182. }
  183. }
  184. };
  185. }
  186. test_i_u_f!(digest_test_i_u_f_sha1, digest::SHA1_FOR_LEGACY_USE_ONLY);
  187. test_i_u_f!(digest_test_i_u_f_sha256, digest::SHA256);
  188. test_i_u_f!(digest_test_i_u_f_sha384, digest::SHA384);
  189. test_i_u_f!(digest_test_i_u_f_sha512, digest::SHA512);
  190. /// See https://bugzilla.mozilla.org/show_bug.cgi?id=610162. This tests the
  191. /// calculation of 8GB of the byte 123.
  192. ///
  193. /// You can verify the expected values in many ways. One way is
  194. /// `python ~/p/write_big.py`, where write_big.py is:
  195. ///
  196. /// ```python
  197. /// chunk = bytearray([123] * (16 * 1024))
  198. /// with open('tempfile', 'w') as f:
  199. /// for i in xrange(0, 8 * 1024 * 1024 * 1024, len(chunk)):
  200. /// f.write(chunk)
  201. /// ```
  202. /// Then:
  203. ///
  204. /// ```sh
  205. /// sha1sum -b tempfile
  206. /// sha256sum -b tempfile
  207. /// sha384sum -b tempfile
  208. /// sha512sum -b tempfile
  209. /// ```
  210. ///
  211. /// This is not run in dev (debug) builds because it is too slow.
  212. macro_rules! test_large_digest {
  213. ( $test_name:ident, $alg:expr, $len:expr, $expected:expr) => {
  214. #[cfg(not(debug_assertions))]
  215. #[test]
  216. // TODO: #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
  217. fn $test_name() {
  218. let chunk = vec![123u8; 16 * 1024];
  219. let chunk_len = chunk.len() as u64;
  220. let mut ctx = digest::Context::new(&$alg);
  221. let mut hashed = 0u64;
  222. loop {
  223. ctx.update(&chunk);
  224. hashed += chunk_len;
  225. if hashed >= 8u64 * 1024 * 1024 * 1024 {
  226. break;
  227. }
  228. }
  229. let calculated = ctx.finish();
  230. let expected: [u8; $len] = $expected;
  231. assert_eq!(&expected[..], calculated.as_ref());
  232. }
  233. };
  234. }
  235. // XXX: This test is too slow on Android ARM.
  236. #[cfg(any(not(target_os = "android"), not(target_arch = "arm")))]
  237. test_large_digest!(
  238. digest_test_large_digest_sha1,
  239. digest::SHA1_FOR_LEGACY_USE_ONLY,
  240. 160 / 8,
  241. [
  242. 0xCA, 0xC3, 0x4C, 0x31, 0x90, 0x5B, 0xDE, 0x3B, 0xE4, 0x0D, 0x46, 0x6D, 0x70, 0x76, 0xAD,
  243. 0x65, 0x3C, 0x20, 0xE4, 0xBD
  244. ]
  245. );
  246. test_large_digest!(
  247. digest_test_large_digest_sha256,
  248. digest::SHA256,
  249. 256 / 8,
  250. [
  251. 0x8D, 0xD1, 0x6D, 0xD8, 0xB2, 0x5A, 0x29, 0xCB, 0x7F, 0xB9, 0xAE, 0x86, 0x72, 0xE9, 0xCE,
  252. 0xD6, 0x65, 0x4C, 0xB6, 0xC3, 0x5C, 0x58, 0x21, 0xA7, 0x07, 0x97, 0xC5, 0xDD, 0xAE, 0x5C,
  253. 0x68, 0xBD
  254. ]
  255. );
  256. test_large_digest!(
  257. digest_test_large_digest_sha384,
  258. digest::SHA384,
  259. 384 / 8,
  260. [
  261. 0x3D, 0xFE, 0xC1, 0xA9, 0xD0, 0x9F, 0x08, 0xD5, 0xBB, 0xE8, 0x7C, 0x9E, 0xE0, 0x0A, 0x87,
  262. 0x0E, 0xB0, 0xEA, 0x8E, 0xEA, 0xDB, 0x82, 0x36, 0xAE, 0x74, 0xCF, 0x9F, 0xDC, 0x86, 0x1C,
  263. 0xE3, 0xE9, 0xB0, 0x68, 0xCD, 0x19, 0x3E, 0x39, 0x90, 0x02, 0xE1, 0x58, 0x5D, 0x66, 0xC4,
  264. 0x55, 0x11, 0x9B
  265. ]
  266. );
  267. test_large_digest!(
  268. digest_test_large_digest_sha512,
  269. digest::SHA512,
  270. 512 / 8,
  271. [
  272. 0xFC, 0x8A, 0x98, 0x20, 0xFC, 0x82, 0xD8, 0x55, 0xF8, 0xFF, 0x2F, 0x6E, 0xAE, 0x41, 0x60,
  273. 0x04, 0x08, 0xE9, 0x49, 0xD7, 0xCD, 0x1A, 0xED, 0x22, 0xEB, 0x55, 0xE1, 0xFD, 0x80, 0x50,
  274. 0x3B, 0x01, 0x2F, 0xC6, 0xF4, 0x33, 0x86, 0xFB, 0x60, 0x75, 0x2D, 0xA5, 0xA9, 0x93, 0xE7,
  275. 0x00, 0x45, 0xA8, 0x49, 0x1A, 0x6B, 0xEC, 0x9C, 0x98, 0xC8, 0x19, 0xA6, 0xA9, 0x88, 0x3E,
  276. 0x2F, 0x09, 0xB9, 0x9A
  277. ]
  278. );
  279. // TODO: test_large_digest!(digest_test_large_digest_sha512_256,
  280. // digest::SHA512_256, 256 / 8, [ ... ]);
  281. #[test]
  282. #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
  283. fn test_fmt_algorithm() {
  284. assert_eq!("SHA1", &format!("{:?}", digest::SHA1_FOR_LEGACY_USE_ONLY));
  285. assert_eq!("SHA256", &format!("{:?}", digest::SHA256));
  286. assert_eq!("SHA384", &format!("{:?}", digest::SHA384));
  287. assert_eq!("SHA512", &format!("{:?}", digest::SHA512));
  288. assert_eq!("SHA512_256", &format!("{:?}", digest::SHA512_256));
  289. }
  290. #[test]
  291. #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
  292. fn digest_test_fmt() {
  293. assert_eq!(
  294. "SHA1:b7e23ec29af22b0b4e41da31e868d57226121c84",
  295. &format!(
  296. "{:?}",
  297. digest::digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, b"hello, world")
  298. )
  299. );
  300. assert_eq!(
  301. "SHA256:09ca7e4eaa6e8ae9c7d261167129184883644d\
  302. 07dfba7cbfbc4c8a2e08360d5b",
  303. &format!("{:?}", digest::digest(&digest::SHA256, b"hello, world"))
  304. );
  305. assert_eq!(
  306. "SHA384:1fcdb6059ce05172a26bbe2a3ccc88ed5a8cd5\
  307. fc53edfd9053304d429296a6da23b1cd9e5c9ed3bb34f0\
  308. 0418a70cdb7e",
  309. &format!("{:?}", digest::digest(&digest::SHA384, b"hello, world"))
  310. );
  311. assert_eq!(
  312. "SHA512:8710339dcb6814d0d9d2290ef422285c9322b7\
  313. 163951f9a0ca8f883d3305286f44139aa374848e4174f5\
  314. aada663027e4548637b6d19894aec4fb6c46a139fbf9",
  315. &format!("{:?}", digest::digest(&digest::SHA512, b"hello, world"))
  316. );
  317. assert_eq!(
  318. "SHA512_256:11f2c88c04f0a9c3d0970894ad2472505e\
  319. 0bc6e8c7ec46b5211cd1fa3e253e62",
  320. &format!("{:?}", digest::digest(&digest::SHA512_256, b"hello, world"))
  321. );
  322. }