--- /dev/null
+namespace CryptoFile
+
+// Some cryptography primitives specific to CryptoFile.
+module internal Crypto =
+ open System.Security.Cryptography
+ open System.IO
+
+ type Data = byte[]
+
+ let rsaKeySize = 2048
+
+ /// Returns a cryptographically strong sequence of bytes.
+ let rand size : byte[] =
+ let result = Array.zeroCreate size
+ let generator = new RNGCryptoServiceProvider ()
+ generator.GetBytes result
+ result
+
+ /// Generate a new RSA key pair: (public * private).
+ let generateRSAKeysPair : Key * Key =
+ use rsa = new RSACryptoServiceProvider (rsaKeySize)
+ try
+ rsa.ToXmlString false, rsa.ToXmlString true
+ finally
+ rsa.PersistKeyInCsp <- false
+
+ let encryptRSA (publicKey : Key) (plaindata : Data) : Data =
+ use rsa = new RSACryptoServiceProvider (rsaKeySize)
+ try
+ rsa.FromXmlString publicKey
+ rsa.Encrypt (plaindata, false) // Uses PKCS#1 v1.5 padding.
+ finally
+ rsa.PersistKeyInCsp <- false
+
+ let decryptRSA (privateKey : Key) (cipherdata : Data) : Data =
+ use rsa = new RSACryptoServiceProvider (rsaKeySize)
+ try
+ rsa.FromXmlString privateKey
+ rsa.Decrypt (cipherdata, false) // Uses PKCS#1 v1.5 padding.
+ finally
+ rsa.PersistKeyInCsp <- false
+
+ /// Produces a signature from a given hash.
+ let signRSA (privKey : Key) (sha256 : Data) : Data =
+ use rsa = new RSACryptoServiceProvider (rsaKeySize)
+ try
+ rsa.FromXmlString privKey
+ rsa.SignHash (sha256, CryptoConfig.MapNameToOID "SHA256")
+ finally
+ rsa.PersistKeyInCsp <- false
+
+ /// Verify a signature against a given hash.
+ let verifySignRSA (pubKey : Key) (sha256 : Data) (signature : Data) : bool =
+ use rsa = new RSACryptoServiceProvider (rsaKeySize)
+ try
+ rsa.FromXmlString pubKey
+ rsa.VerifyHash (sha256, CryptoConfig.MapNameToOID "SHA256", signature)
+ finally
+ rsa.PersistKeyInCsp <- false
+
+ /// Returns an encrypted output stream.
+ let encryptAES (key : byte[]) (iv : byte[]) (outputStream : Stream) : Stream =
+ assert (key.Length = 32 && iv.Length = 16)
+ use aes = new AesManaged ()
+ aes.KeySize <- 256
+ let encryptor = aes.CreateEncryptor (key, iv)
+ new CryptoStream (outputStream, encryptor, CryptoStreamMode.Write) :> Stream
+
+ /// Returns a decrypted input stream.
+ let decryptAES (key : byte[]) (iv : byte[]) (inputStream : Stream) : Stream =
+ assert (key.Length = 32 && iv.Length = 16)
+ use aes = new AesManaged ()
+ aes.KeySize <- 256
+ let decryptor = aes.CreateDecryptor (key, iv)
+ new CryptoStream (inputStream, decryptor, CryptoStreamMode.Read) :> Stream