Replace AESManager by AesCryptoServiceProvider.
[crypto_lab2.git] / labo2-fsharp / CryptoFile / API.fs
index 1601c97..424959d 100644 (file)
@@ -28,21 +28,23 @@ module API =
         let filenameKey = "filename"
         let modificationTimeKey = "file-modification-time"
 
+    let internal (@@) a1 a2 = Array.append a1 a2
+
     let generatKeysPair : Key * Key = Crypto.generateRSAKeysPair
 
     let encryptFile (inputFilePath : string) (outputFilePath : string) (signaturePrivKey: Key) (cryptPubKey : Key)  =
         let keyAES, keyMAC, iv = Crypto.rand 32, Crypto.rand 32, Crypto.rand 16
         let fileInfo = new FileInfo (inputFilePath)
-        use inputStream = new FileStream (inputFilePath, FileMode.Open, FileAccess.Read)
-        use outputStream = new FileStream (outputFilePath, FileMode.Create, FileAccess.Write)
+        use inputStream = fileInfo.OpenRead ()
+        use outputStream = new FileStream (outputFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, 4096 * 100)
         let writer = new BinaryWriter (outputStream)
 
-        writer.Seek (32 + 256, SeekOrigin.Current) |> ignore // Skips mac and signature. They will be written later.
+        outputStream.Position <- 32L + 256L // Skips mac and signature. They will be written later.
 
-        Crypto.encryptRSA cryptPubKey (Array.append keyAES <| Array.append keyMAC iv) |> writer.Write
+        Crypto.encryptRSA cryptPubKey (keyAES @@ keyMAC @@ iv) |> writer.Write
 
         // Plaintext -> cryptoStream -> hmacStream -> cyphertext.
-        let (hmacStream, hmac) = Crypto.HMACStream keyMAC outputStream
+        let hmacStream, hmac = Crypto.HMACStream keyMAC outputStream
         use cryptoStream = Crypto.encryptAES keyAES iv hmacStream
         let cryptoWriter = new BinaryWriter (cryptoStream)
 
@@ -62,12 +64,19 @@ module API =
         // Write the signature.
         Crypto.signRSA signaturePrivKey hmac.Hash |> writer.Write
 
+    // May raise one of the following error:
+    //  * IntegrityError
+    //  * SignatureMismatch 
+    //  * UnableToDecryptAESKeys
     let decryptFile (sourceFilePath : string) (targetDirPath : string) (signaturePubKey: Key) (decryptPrivKey : Key) =
         use inputStream = new FileStream (sourceFilePath, FileMode.Open, FileAccess.Read)
         use reader = new BinaryReader (inputStream)
         let mac = reader.ReadBytes 32
         let signature = reader.ReadBytes 256
-        let keys = reader.ReadBytes 256 |> Crypto.decryptRSA decryptPrivKey
+        let keys = 
+            try reader.ReadBytes 256 |> Crypto.decryptRSA decryptPrivKey
+            with 
+                | :? Security.Cryptography.CryptographicException -> raise UnableToDecryptAESKeys
         let keyAES = keys.[0..31]
         let keyMAC = keys.[32..63]
         let iv = keys.[64..79]
@@ -76,7 +85,7 @@ module API =
         let mac' = Crypto.ComputeHMAC keyMAC inputStream
         if mac' <> mac then
             raise IntegrityError
-
+        
         // Authentication validation.
         if not <| Crypto.verifySignRSA signaturePubKey mac' signature then
             raise SignatureMismatch