/httpbis-test/src/openssl_test_key_gen.rs

https://github.com/stepancheg/rust-http2 · Rust · 138 lines · 118 code · 17 blank · 3 comment · 0 complexity · f71477e6454a39864ecac590c51336c4 MD5 · raw file

  1. //! Utilities to generate keys for tests.
  2. //!
  3. //! This is copy-paste from tokio-tls.
  4. use std::env;
  5. use std::fs::File;
  6. use std::io::Read;
  7. use std::io::Write;
  8. use std::process::Command;
  9. use std::process::Stdio;
  10. use std::ptr;
  11. use std::sync::Once;
  12. pub struct ClientKeys {
  13. pub cert_der: Vec<u8>,
  14. }
  15. pub struct ServerKeys {
  16. pub pkcs12: Vec<u8>,
  17. pub pkcs12_password: String,
  18. pub pem: Vec<u8>,
  19. }
  20. pub struct Keys {
  21. pub client: ClientKeys,
  22. pub server: ServerKeys,
  23. }
  24. pub fn keys() -> &'static Keys {
  25. static INIT: Once = Once::new();
  26. static mut KEYS: *mut Keys = ptr::null_mut();
  27. INIT.call_once(|| {
  28. let path = t!(env::current_exe());
  29. let path = path.parent().unwrap();
  30. let keyfile = path.join("test.key");
  31. let certfile = path.join("test.crt");
  32. let config = path.join("openssl.config");
  33. File::create(&config)
  34. .unwrap()
  35. .write_all(
  36. b"\
  37. [req]\n\
  38. distinguished_name=dn\n\
  39. [dn]\n\
  40. CN=localhost\n\
  41. [ext]\n\
  42. basicConstraints=CA:FALSE,pathlen:0\n\
  43. subjectAltName = @alt_names\n\
  44. extendedKeyUsage=serverAuth,clientAuth\n\
  45. [alt_names]\n\
  46. DNS.1 = localhost\n\
  47. ",
  48. )
  49. .unwrap();
  50. let subj = "/C=US/ST=Denial/L=Sprintfield/O=Dis/CN=localhost";
  51. let output = t!(Command::new("openssl")
  52. .arg("req")
  53. .arg("-nodes")
  54. .arg("-x509")
  55. .arg("-newkey")
  56. .arg("rsa:2048")
  57. .arg("-config")
  58. .arg(&config)
  59. .arg("-extensions")
  60. .arg("ext")
  61. .arg("-subj")
  62. .arg(subj)
  63. .arg("-keyout")
  64. .arg(&keyfile)
  65. .arg("-out")
  66. .arg(&certfile)
  67. .arg("-days")
  68. .arg("1")
  69. .output());
  70. assert!(output.status.success());
  71. let crtout = t!(Command::new("openssl")
  72. .arg("x509")
  73. .arg("-outform")
  74. .arg("der")
  75. .arg("-in")
  76. .arg(&certfile)
  77. .output());
  78. assert!(crtout.status.success());
  79. let pkcs12out = t!(Command::new("openssl")
  80. .arg("pkcs12")
  81. .arg("-export")
  82. .arg("-nodes")
  83. .arg("-inkey")
  84. .arg(&keyfile)
  85. .arg("-in")
  86. .arg(&certfile)
  87. .arg("-password")
  88. .arg("pass:foobar")
  89. .output());
  90. assert!(pkcs12out.status.success());
  91. let pem = pkcs12_to_pem(&pkcs12out.stdout, "foobar");
  92. let keys = Box::new(Keys {
  93. client: ClientKeys {
  94. cert_der: crtout.stdout,
  95. },
  96. server: ServerKeys {
  97. pem,
  98. pkcs12: pkcs12out.stdout,
  99. pkcs12_password: "foobar".to_owned(),
  100. },
  101. });
  102. unsafe {
  103. KEYS = Box::into_raw(keys);
  104. }
  105. });
  106. unsafe { &*KEYS }
  107. }
  108. fn pkcs12_to_pem(pkcs12: &[u8], passin: &str) -> Vec<u8> {
  109. let command = t!(Command::new("openssl")
  110. .arg("pkcs12")
  111. .arg("-passin")
  112. .arg(&format!("pass:{}", passin))
  113. .arg("-nodes")
  114. .stdin(Stdio::piped())
  115. .stdout(Stdio::piped())
  116. .spawn());
  117. t!(command.stdin.unwrap().write_all(pkcs12));
  118. let mut pem = Vec::new();
  119. t!(command.stdout.unwrap().read_to_end(&mut pem));
  120. pem
  121. }