+ 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 =
+ try reader.ReadBytes 256 |> Crypto.decryptRSA decryptPrivKey
+ with
+ | :? Security.Cryptography.CryptographicException -> raise UnableToDecryptAESKeys
+ let keyAES = keys.[0..15]
+ let keyMAC = keys.[16..47]
+ let iv = keys.[48..63]
+
+ // Integrity validation.
+ let mac' = Crypto.ComputeHMAC keyMAC inputStream
+ if mac' <> mac then
+ raise IntegrityError
+
+ // Authentication validation.
+ if not <| Crypto.verifySignRSA signaturePubKey mac' signature then
+ raise SignatureMismatch
+
+ // Decrypt metadata.
+ inputStream.Position <- 32L + 256L + 256L
+ use cryptoStream = Crypto.decryptAES keyAES iv inputStream
+ let metadata = Metadata cryptoStream
+
+ // Create the file and write its content and metadata.
+ let filePath = Path.Combine (targetDirPath, metadata.get MetadataKeys.filename)
+ let modificationTime = DateTime (metadata.get MetadataKeys.modificationTime |> int64)
+ let fileInfo = FileInfo filePath
+ using (fileInfo.Create ()) <| fun outputStream -> cryptoStream.CopyTo outputStream
+ fileInfo.LastWriteTimeUtc <- modificationTime
+
\ No newline at end of file