cryptoutil.rs 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. use rand;
  2. use gmp::Mpz;
  3. use std::num::FromPrimitive;
  4. use crypto;
  5. use crypto::mac::Mac;
  6. use std::io::Write;
  7. use util;
  8. lazy_static! {
  9. static ref DH_GENERATOR: Mpz = Mpz::from_u64(0x2).unwrap();
  10. static ref DH_PRIME: Mpz = Mpz::from_bytes_be(&[
  11. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9,
  12. 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6,
  13. 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e,
  14. 0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
  15. 0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e,
  16. 0x34, 0x04, 0xdd, 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a,
  17. 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14,
  18. 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
  19. 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4,
  20. 0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, 0xff, 0xff,
  21. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ]);
  22. }
  23. pub struct Crypto {
  24. private_key: Mpz,
  25. public_key: Mpz,
  26. shared: Option<SharedKeys>,
  27. }
  28. pub struct SharedKeys {
  29. pub challenge: Vec<u8>,
  30. pub send_key: Vec<u8>,
  31. pub recv_key: Vec<u8>
  32. }
  33. impl Crypto {
  34. pub fn new() -> Crypto {
  35. let key_data = util::rand_vec(&mut rand::thread_rng(), 95);
  36. Self::new_with_key(&key_data)
  37. }
  38. pub fn new_with_key(key_data: &[u8]) -> Crypto {
  39. let private_key = Mpz::from_bytes_be(key_data);
  40. let public_key = DH_GENERATOR.powm(&private_key, &DH_PRIME);
  41. Crypto {
  42. private_key: private_key,
  43. public_key: public_key,
  44. shared: None,
  45. }
  46. }
  47. pub fn setup(&mut self, remote_key: &[u8], client_packet: &[u8], server_packet: &[u8]) {
  48. let shared_key = Mpz::from_bytes_be(remote_key).powm(&self.private_key, &DH_PRIME);
  49. let mut data = Vec::with_capacity(0x54);
  50. let mut h = crypto::hmac::Hmac::new(crypto::sha1::Sha1::new(), &shared_key.to_bytes_be());
  51. for i in 1..6 {
  52. h.input(client_packet);
  53. h.input(server_packet);
  54. h.input(&[i]);
  55. data.write(&h.result().code()).unwrap();
  56. h.reset();
  57. }
  58. h = crypto::hmac::Hmac::new(crypto::sha1::Sha1::new(), &data[..0x14]);
  59. h.input(client_packet);
  60. h.input(server_packet);
  61. self.shared = Some(SharedKeys{
  62. challenge: h.result().code().to_vec(),
  63. send_key: data[0x14..0x34].to_vec(),
  64. recv_key: data[0x34..0x54].to_vec()
  65. });
  66. }
  67. pub fn public_key(&self) -> Vec<u8> {
  68. return self.public_key.to_bytes_be();
  69. }
  70. pub fn shared(&self) -> &SharedKeys {
  71. match self.shared {
  72. Some(ref shared) => shared,
  73. None => panic!("ABC")
  74. }
  75. }
  76. }