authentication.rs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. use byteorder::{BigEndian, ByteOrder};
  2. use crypto;
  3. use crypto::aes;
  4. use crypto::digest::Digest;
  5. use crypto::hmac::Hmac;
  6. use crypto::mac::Mac;
  7. use crypto::pbkdf2::pbkdf2;
  8. use crypto::sha1::Sha1;
  9. use protobuf::ProtobufEnum;
  10. use std::io::{self, Read, Write};
  11. use std::fs::File;
  12. use std::path::Path;
  13. use rustc_serialize::base64::{self, FromBase64, ToBase64};
  14. use rustc_serialize::json;
  15. use protocol::authentication::AuthenticationType;
  16. #[derive(Debug, Clone)]
  17. pub struct Credentials {
  18. pub username: String,
  19. pub auth_type: AuthenticationType,
  20. pub auth_data: Vec<u8>,
  21. }
  22. #[derive(Debug, Clone)]
  23. #[derive(RustcDecodable, RustcEncodable)]
  24. struct StoredCredentials {
  25. pub username: String,
  26. pub auth_type: i32,
  27. pub auth_data: String,
  28. }
  29. impl Credentials {
  30. pub fn with_password(username: String, password: String) -> Credentials {
  31. Credentials {
  32. username: username,
  33. auth_type: AuthenticationType::AUTHENTICATION_USER_PASS,
  34. auth_data: password.into_bytes(),
  35. }
  36. }
  37. pub fn with_blob(username: String, encrypted_blob: &str, device_id: &str) -> Credentials {
  38. fn read_u8<R: Read>(stream: &mut R) -> io::Result<u8> {
  39. let mut data = [0u8];
  40. try!(stream.read_exact(&mut data));
  41. Ok(data[0])
  42. }
  43. fn read_int<R: Read>(stream: &mut R) -> io::Result<u32> {
  44. let lo = try!(read_u8(stream)) as u32;
  45. if lo & 0x80 == 0 {
  46. return Ok(lo);
  47. }
  48. let hi = try!(read_u8(stream)) as u32;
  49. Ok(lo & 0x7f | hi << 7)
  50. }
  51. fn read_bytes<R: Read>(stream: &mut R) -> io::Result<Vec<u8>> {
  52. let length = try!(read_int(stream));
  53. let mut data = vec![0u8; length as usize];
  54. try!(stream.read_exact(&mut data));
  55. Ok(data)
  56. }
  57. let encrypted_blob = encrypted_blob.from_base64().unwrap();
  58. let secret = {
  59. let mut data = [0u8; 20];
  60. let mut h = crypto::sha1::Sha1::new();
  61. h.input(device_id.as_bytes());
  62. h.result(&mut data);
  63. data
  64. };
  65. let key = {
  66. let mut data = [0u8; 24];
  67. let mut mac = Hmac::new(Sha1::new(), &secret);
  68. pbkdf2(&mut mac, username.as_bytes(), 0x100, &mut data[0..20]);
  69. let mut hash = Sha1::new();
  70. hash.input(&data[0..20]);
  71. hash.result(&mut data[0..20]);
  72. BigEndian::write_u32(&mut data[20..], 20);
  73. data
  74. };
  75. let blob = {
  76. // Anyone know what this block mode is ?
  77. let mut data = vec![0u8; encrypted_blob.len()];
  78. let mut cipher = aes::ecb_decryptor(aes::KeySize::KeySize192,
  79. &key,
  80. crypto::blockmodes::NoPadding);
  81. cipher.decrypt(&mut crypto::buffer::RefReadBuffer::new(&encrypted_blob),
  82. &mut crypto::buffer::RefWriteBuffer::new(&mut data),
  83. true)
  84. .unwrap();
  85. let l = encrypted_blob.len();
  86. for i in 0..l - 0x10 {
  87. data[l - i - 1] ^= data[l - i - 0x11];
  88. }
  89. data
  90. };
  91. let mut cursor = io::Cursor::new(&blob);
  92. read_u8(&mut cursor).unwrap();
  93. read_bytes(&mut cursor).unwrap();
  94. read_u8(&mut cursor).unwrap();
  95. let auth_type = read_int(&mut cursor).unwrap();
  96. let auth_type = AuthenticationType::from_i32(auth_type as i32).unwrap();
  97. read_u8(&mut cursor).unwrap();
  98. let auth_data = read_bytes(&mut cursor).unwrap();;
  99. Credentials {
  100. username: username,
  101. auth_type: auth_type,
  102. auth_data: auth_data,
  103. }
  104. }
  105. pub fn from_reader<R: Read>(mut reader: R) -> Credentials {
  106. let mut contents = String::new();
  107. reader.read_to_string(&mut contents).unwrap();
  108. json::decode::<StoredCredentials>(&contents).unwrap().into()
  109. }
  110. pub fn from_file<P: AsRef<Path>>(path: P) -> Credentials {
  111. let file = File::open(path).unwrap();
  112. Credentials::from_reader(file)
  113. }
  114. pub fn save_to_writer<W: Write>(&self, writer: &mut W) {
  115. let contents = json::encode::<StoredCredentials>(&self.clone().into()).unwrap();
  116. writer.write_all(contents.as_bytes()).unwrap();
  117. }
  118. pub fn save_to_file<P: AsRef<Path>>(&self, path: P) {
  119. let mut file = File::create(path).unwrap();
  120. self.save_to_writer(&mut file)
  121. }
  122. }
  123. impl From<Credentials> for StoredCredentials {
  124. fn from(credentials: Credentials) -> StoredCredentials {
  125. StoredCredentials {
  126. username: credentials.username,
  127. auth_type: credentials.auth_type.value(),
  128. auth_data: credentials.auth_data.to_base64(base64::STANDARD),
  129. }
  130. }
  131. }
  132. impl From<StoredCredentials> for Credentials {
  133. fn from(credentials: StoredCredentials) -> Credentials {
  134. Credentials {
  135. username: credentials.username,
  136. auth_type: AuthenticationType::from_i32(credentials.auth_type).unwrap(),
  137. auth_data: credentials.auth_data.from_base64().unwrap(),
  138. }
  139. }
  140. }