+ use inputStream = new FileStream (sourceFilePath, FileMode.Open, FileAccess.Read)
+ use reader = new BinaryReader (inputStream)
+ let mac = reader.ReadBytes hmacSize
+ let signature = reader.ReadBytes signatureSize
+ let keys =
+ try reader.ReadBytes keysSize |> Crypto.decryptRSA decryptPrivKey
+ with
+ | :? Security.Cryptography.CryptographicException -> raise UnableToDecryptKeys
+ 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 <- (int64 <| hmacSize + signatureSize + keysSize)
+ 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 ()) cryptoStream.CopyTo // We have to close the result file before updating the modification time.
+ fileInfo.LastWriteTimeUtc <- modificationTime
+
\ No newline at end of file