ecdsa_tests.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Copyright 2015-2016 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::{
  15. rand,
  16. signature::{self, KeyPair},
  17. test, test_file,
  18. };
  19. // ECDSA *signing* tests are in src/ec/ecdsa/signing.rs.
  20. #[test]
  21. fn ecdsa_from_pkcs8_test() {
  22. test::run(
  23. test_file!("ecdsa_from_pkcs8_tests.txt"),
  24. |section, test_case| {
  25. assert_eq!(section, "");
  26. let curve_name = test_case.consume_string("Curve");
  27. let ((this_fixed, this_asn1), (other_fixed, other_asn1)) = match curve_name.as_str() {
  28. "P-256" => (
  29. (
  30. &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
  31. &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
  32. ),
  33. (
  34. &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
  35. &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
  36. ),
  37. ),
  38. "P-384" => (
  39. (
  40. &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
  41. &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
  42. ),
  43. (
  44. &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
  45. &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
  46. ),
  47. ),
  48. _ => unreachable!(),
  49. };
  50. let input = test_case.consume_bytes("Input");
  51. let error = test_case.consume_optional_string("Error");
  52. match (
  53. signature::EcdsaKeyPair::from_pkcs8(this_fixed, &input),
  54. error.clone(),
  55. ) {
  56. (Ok(_), None) => (),
  57. (Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
  58. (Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
  59. (Err(actual), Some(expected)) => assert_eq!(format!("{}", actual), expected),
  60. };
  61. match (
  62. signature::EcdsaKeyPair::from_pkcs8(this_asn1, &input),
  63. error,
  64. ) {
  65. (Ok(_), None) => (),
  66. (Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
  67. (Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
  68. (Err(actual), Some(expected)) => assert_eq!(format!("{}", actual), expected),
  69. };
  70. assert!(signature::EcdsaKeyPair::from_pkcs8(other_fixed, &input).is_err());
  71. assert!(signature::EcdsaKeyPair::from_pkcs8(other_asn1, &input).is_err());
  72. Ok(())
  73. },
  74. );
  75. }
  76. // Verify that, at least, we generate PKCS#8 documents that we can read.
  77. #[test]
  78. fn ecdsa_generate_pkcs8_test() {
  79. let rng = rand::SystemRandom::new();
  80. for alg in &[
  81. &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
  82. &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
  83. &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
  84. &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
  85. ] {
  86. let pkcs8 = signature::EcdsaKeyPair::generate_pkcs8(alg, &rng).unwrap();
  87. println!();
  88. for b in pkcs8.as_ref() {
  89. print!("{:02x}", *b);
  90. }
  91. println!();
  92. println!();
  93. #[cfg(feature = "alloc")]
  94. let _ = signature::EcdsaKeyPair::from_pkcs8(*alg, pkcs8.as_ref()).unwrap();
  95. }
  96. }
  97. #[test]
  98. fn signature_ecdsa_verify_asn1_test() {
  99. test::run(
  100. test_file!("ecdsa_verify_asn1_tests.txt"),
  101. |section, test_case| {
  102. assert_eq!(section, "");
  103. let curve_name = test_case.consume_string("Curve");
  104. let digest_name = test_case.consume_string("Digest");
  105. let msg = test_case.consume_bytes("Msg");
  106. let public_key = test_case.consume_bytes("Q");
  107. let sig = test_case.consume_bytes("Sig");
  108. let is_valid = test_case.consume_string("Result") == "P (0 )";
  109. let alg = match (curve_name.as_str(), digest_name.as_str()) {
  110. ("P-256", "SHA256") => &signature::ECDSA_P256_SHA256_ASN1,
  111. ("P-256", "SHA384") => &signature::ECDSA_P256_SHA384_ASN1,
  112. ("P-384", "SHA256") => &signature::ECDSA_P384_SHA256_ASN1,
  113. ("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_ASN1,
  114. _ => {
  115. panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
  116. }
  117. };
  118. let actual_result =
  119. signature::UnparsedPublicKey::new(alg, &public_key).verify(&msg, &sig);
  120. assert_eq!(actual_result.is_ok(), is_valid);
  121. Ok(())
  122. },
  123. );
  124. }
  125. #[test]
  126. fn signature_ecdsa_verify_fixed_test() {
  127. test::run(
  128. test_file!("ecdsa_verify_fixed_tests.txt"),
  129. |section, test_case| {
  130. assert_eq!(section, "");
  131. let curve_name = test_case.consume_string("Curve");
  132. let digest_name = test_case.consume_string("Digest");
  133. let msg = test_case.consume_bytes("Msg");
  134. let public_key = test_case.consume_bytes("Q");
  135. let sig = test_case.consume_bytes("Sig");
  136. let expected_result = test_case.consume_string("Result");
  137. let alg = match (curve_name.as_str(), digest_name.as_str()) {
  138. ("P-256", "SHA256") => &signature::ECDSA_P256_SHA256_FIXED,
  139. ("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_FIXED,
  140. _ => {
  141. panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
  142. }
  143. };
  144. let is_valid = expected_result == "P (0 )";
  145. let actual_result =
  146. signature::UnparsedPublicKey::new(alg, &public_key).verify(&msg, &sig);
  147. assert_eq!(actual_result.is_ok(), is_valid);
  148. Ok(())
  149. },
  150. );
  151. }
  152. #[test]
  153. fn ecdsa_test_public_key_coverage() {
  154. const PRIVATE_KEY: &[u8] = include_bytes!("ecdsa_test_private_key_p256.p8");
  155. const PUBLIC_KEY: &[u8] = include_bytes!("ecdsa_test_public_key_p256.der");
  156. const PUBLIC_KEY_DEBUG: &str = include_str!("ecdsa_test_public_key_p256_debug.txt");
  157. let key_pair = signature::EcdsaKeyPair::from_pkcs8(
  158. &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
  159. PRIVATE_KEY,
  160. )
  161. .unwrap();
  162. // Test `AsRef<[u8]>`
  163. assert_eq!(key_pair.public_key().as_ref(), PUBLIC_KEY);
  164. // Test `Clone`.
  165. #[allow(clippy::clone_on_copy, clippy::redundant_clone)]
  166. let _: <signature::EcdsaKeyPair as KeyPair>::PublicKey = key_pair.public_key().clone();
  167. // Test `Copy`.
  168. let _: <signature::EcdsaKeyPair as KeyPair>::PublicKey = *key_pair.public_key();
  169. // Test `Debug`.
  170. assert_eq!(PUBLIC_KEY_DEBUG, format!("{:?}", key_pair.public_key()));
  171. assert_eq!(
  172. format!("EcdsaKeyPair {{ public_key: {:?} }}", key_pair.public_key()),
  173. format!("{:?}", key_pair)
  174. );
  175. }
  176. // This test is not a known-answer test, though it re-uses the known-answer
  177. // test vectors. Because the nonce is randomized, the signature will be
  178. // different each time. Because of that, here we simply verify that the
  179. // signature verifies correctly. The known-answer tests themselves are in
  180. // ecsda/signing.rs.
  181. #[test]
  182. fn signature_ecdsa_sign_fixed_sign_and_verify_test() {
  183. let rng = rand::SystemRandom::new();
  184. test::run(
  185. test_file!("../src/ec/suite_b/ecdsa/ecdsa_sign_fixed_tests.txt"),
  186. |section, test_case| {
  187. assert_eq!(section, "");
  188. let curve_name = test_case.consume_string("Curve");
  189. let digest_name = test_case.consume_string("Digest");
  190. let msg = test_case.consume_bytes("Msg");
  191. let d = test_case.consume_bytes("d");
  192. let q = test_case.consume_bytes("Q");
  193. // Ignored since the actual signature will use a randomized nonce.
  194. let _k = test_case.consume_bytes("k");
  195. let _expected_result = test_case.consume_bytes("Sig");
  196. let (signing_alg, verification_alg) = match (curve_name.as_str(), digest_name.as_str())
  197. {
  198. ("P-256", "SHA256") => (
  199. &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
  200. &signature::ECDSA_P256_SHA256_FIXED,
  201. ),
  202. ("P-384", "SHA384") => (
  203. &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
  204. &signature::ECDSA_P384_SHA384_FIXED,
  205. ),
  206. _ => {
  207. panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
  208. }
  209. };
  210. let private_key =
  211. signature::EcdsaKeyPair::from_private_key_and_public_key(signing_alg, &d, &q)
  212. .unwrap();
  213. let signature = private_key.sign(&rng, &msg).unwrap();
  214. let public_key = signature::UnparsedPublicKey::new(verification_alg, q);
  215. assert_eq!(public_key.verify(&msg, signature.as_ref()), Ok(()));
  216. Ok(())
  217. },
  218. );
  219. }
  220. // This test is not a known-answer test, though it re-uses the known-answer
  221. // test vectors. Because the nonce is randomized, the signature will be
  222. // different each time. Because of that, here we simply verify that the
  223. // signature verifies correctly. The known-answer tests themselves are in
  224. // ecsda/signing.rs.
  225. #[test]
  226. fn signature_ecdsa_sign_asn1_test() {
  227. let rng = rand::SystemRandom::new();
  228. test::run(
  229. test_file!("../src/ec/suite_b/ecdsa/ecdsa_sign_asn1_tests.txt"),
  230. |section, test_case| {
  231. assert_eq!(section, "");
  232. let curve_name = test_case.consume_string("Curve");
  233. let digest_name = test_case.consume_string("Digest");
  234. let msg = test_case.consume_bytes("Msg");
  235. let d = test_case.consume_bytes("d");
  236. let q = test_case.consume_bytes("Q");
  237. // Ignored since the actual signature will use a randomized nonce.
  238. let _k = test_case.consume_bytes("k");
  239. let _expected_result = test_case.consume_bytes("Sig");
  240. let (signing_alg, verification_alg) = match (curve_name.as_str(), digest_name.as_str())
  241. {
  242. ("P-256", "SHA256") => (
  243. &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
  244. &signature::ECDSA_P256_SHA256_ASN1,
  245. ),
  246. ("P-384", "SHA384") => (
  247. &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
  248. &signature::ECDSA_P384_SHA384_ASN1,
  249. ),
  250. _ => {
  251. panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
  252. }
  253. };
  254. let private_key =
  255. signature::EcdsaKeyPair::from_private_key_and_public_key(signing_alg, &d, &q)
  256. .unwrap();
  257. let signature = private_key.sign(&rng, &msg).unwrap();
  258. let public_key = signature::UnparsedPublicKey::new(verification_alg, q);
  259. assert_eq!(public_key.verify(&msg, signature.as_ref()), Ok(()));
  260. Ok(())
  261. },
  262. );
  263. }