소스 검색

Properly compute metadata crypto signature with signer

timvisee 7 년 전
부모
커밋
f63b86f0ec
3개의 변경된 파일30개의 추가작업 그리고 21개의 파일을 삭제
  1. 16 17
      api/src/action/download.rs
  2. 13 3
      api/src/crypto/b64.rs
  3. 1 1
      api/src/file/file.rs

+ 16 - 17
api/src/action/download.rs

@@ -1,7 +1,10 @@
 use std::path::Path;
 
 use mime_guess::{get_mime_type, Mime};
-use openssl::symm::{decrypt_aead, encrypt_aead};
+use openssl::hash::MessageDigest;
+use openssl::pkey::PKey;
+use openssl::sign::Signer;
+use openssl::symm::decrypt_aead;
 use reqwest::{
     Client, 
     Error as ReqwestError,
@@ -73,7 +76,7 @@ impl<'a> Download<'a> {
 
         // Get the authentication nonce
         // TODO: don't unwrap here, return an error
-        let nonce = b64::decode(
+        let nonce = b64::decode_standard(
             response.headers()
                 .get_raw(HEADER_AUTH_NONCE)
                 .expect("missing authenticate header") 
@@ -88,18 +91,16 @@ impl<'a> Download<'a> {
                 .expect("missing authentication nonce")
         ).expect("failed to decode authentication nonce");
 
-        // Determine the signature
-        // TODO: use a tag length const here
+        // Compute the cryptographic signature
         // TODO: do not unwrap, return an error
-        let mut sig = vec![0u8; 16];
-		encrypt_aead(
-			KeySet::cipher(),
-			key.auth_key().unwrap(),
-			None,
-			&[],
-			&nonce,
-			&mut sig,
-		).expect("failed to derive signature");
+        let pkey = PKey::hmac(key.auth_key().unwrap())
+            .expect("failed to build HMAC key for signing");
+        let mut signer = Signer::new(MessageDigest::sha256(), &pkey)
+            .expect("failed to build signer");
+        signer.update(&nonce)
+            .expect("failed to feed signer");
+        let sig: Vec<u8> = signer.sign_to_vec()
+            .expect("failed to compute signature");
         let sig_encoded = b64::encode(&sig);
 
         // Get the meta URL, fetch the metadata
@@ -121,7 +122,7 @@ impl<'a> Download<'a> {
 
         // Get the metadata nonce
         // TODO: don't unwrap here, return an error
-        let nonce = b64::decode(
+        let nonce = b64::decode_url(
             response.headers()
                 .get_raw(HEADER_AUTH_NONCE)
                 .expect("missing authenticate header") 
@@ -143,8 +144,6 @@ impl<'a> Download<'a> {
         // Decrypt the metadata
         let metadata = meta_response.decrypt_metadata(&key);
 
-        println!("GOT METADATA: {:?}", metadata);
-
         // // Crpate metadata and a file reader
         // let metadata = self.create_metadata(&key, &file)?;
         // let reader = self.create_reader(&key, reporter.clone())?;
@@ -336,7 +335,7 @@ impl MetadataResponse {
     // TODO: do not unwrap, return a proper error
     pub fn decrypt_metadata(&self, key_set: &KeySet) -> Result<Metadata> {
         // Decode the metadata
-        let raw = b64::decode(&self.meta)
+        let raw = b64::decode_url(&self.meta)
             .expect("failed to decode metadata from server");
 
         // Get the encrypted metadata, and it's tag

+ 13 - 3
api/src/crypto/b64.rs

@@ -6,14 +6,24 @@
 
 extern crate base64;
 
-use self::base64::DecodeError;
+pub use self::base64::{Config, DecodeError};
 
 /// Encode the given byte slice using base64, in an URL-safe manner.
 pub fn encode(input: &[u8]) -> String {
     base64::encode_config(input, base64::URL_SAFE_NO_PAD)
 }
 
+/// Decode the given string as base64, with the given configuration.
+pub fn decode(input: &str, config: Config) -> Result<Vec<u8>, DecodeError> {
+    base64::decode_config(input, config)
+}
+
 /// Decode the given string as base64, in an URL-safe manner.
-pub fn decode(input: &str) -> Result<Vec<u8>, DecodeError> {
-    base64::decode_config(input, base64::URL_SAFE_NO_PAD)
+pub fn decode_url(input: &str) -> Result<Vec<u8>, DecodeError> {
+    decode(input, base64::URL_SAFE_NO_PAD)
+}
+
+/// Decode the given string as base64, with the standaard character set.
+pub fn decode_standard(input: &str) -> Result<Vec<u8>, DecodeError> {
+    decode(input, base64::STANDARD_NO_PAD)
 }

+ 1 - 1
api/src/file/file.rs

@@ -181,7 +181,7 @@ impl DownloadFile {
                 .ok_or(FileParseError::InvalidSecret)?
                 .get(1)
             {
-                secret = b64::decode(raw.as_str().trim())
+                secret = b64::decode_url(raw.as_str().trim())
                         .map_err(|_| FileParseError::InvalidSecret)?
             }
         }