5 open System.Security.Cryptography
7 // Some cryptography primitives specific to CryptoFile.
8 module internal Crypto =
14 /// Returns a cryptographically strong sequence of bytes.
15 let rand size
: byte
[] =
16 let result = Array.zeroCreate
size
17 let generator = new RNGCryptoServiceProvider ()
18 generator.GetBytes result
21 /// Generate a new RSA key pair: (public * private).
22 let generateRSAKeysPair : Key * Key =
23 use rsa = new RSACryptoServiceProvider (rsaKeySize)
24 rsa.ToXmlString false, rsa.ToXmlString true
26 let encryptRSA (publicKey
: Key) (plaindata
: Data) : Data =
27 use rsa = new RSACryptoServiceProvider (rsaKeySize)
28 rsa.FromXmlString publicKey
29 rsa.Encrypt (plaindata
, false) // Uses PKCS#1 v1.5 padding.
31 let decryptRSA (privateKey
: Key) (cipherdata
: Data) : Data =
32 use rsa = new RSACryptoServiceProvider (rsaKeySize)
33 rsa.FromXmlString privateKey
34 rsa.Decrypt (cipherdata
, false) // Uses PKCS#1 v1.5 padding.
36 /// Produces a signature from a given hash.
37 let signRSA (privKey
: Key) (sha256
: Data) : Data =
38 use rsa = new RSACryptoServiceProvider (rsaKeySize)
39 rsa.FromXmlString privKey
40 rsa.SignHash (sha256
, CryptoConfig.MapNameToOID "SHA256")
42 /// Verify a signature against a given hash.
43 let verifySignRSA (pubKey
: Key) (sha256
: Data) (signature
: Data) : bool =
44 use rsa = new RSACryptoServiceProvider (rsaKeySize)
45 rsa.FromXmlString pubKey
46 rsa.VerifyHash (sha256
, CryptoConfig.MapNameToOID "SHA256", signature
)
48 /// Returns an encrypted output stream.
49 let encryptAES (key
: byte
[]) (iv
: byte
[]) (outputStream
: Stream) : CryptoStream =
50 assert (key
.Length = aesKeySize / 8 && iv
.Length = 16)
51 use aes = new AesCryptoServiceProvider () // Default mode is CBC.
52 aes.KeySize <- aesKeySize
53 let encryptor = aes.CreateEncryptor (key
, iv
)
54 new CryptoStream (outputStream
, encryptor, CryptoStreamMode.Write)
56 /// Returns a decrypted input stream.
57 let decryptAES (key
: byte
[]) (iv
: byte
[]) (inputStream
: Stream) : CryptoStream =
58 assert (key
.Length = aesKeySize / 8 && iv
.Length = 16)
59 use aes = new AesCryptoServiceProvider ()
60 aes.KeySize <- aesKeySize
61 let decryptor = aes.CreateDecryptor (key
, iv
)
62 new CryptoStream (inputStream
, decryptor, CryptoStreamMode.Read)
64 // Create a stream to compute the HMAC-SHA256 against all data being written.
65 let HMACStream (key
: byte
[]) (outputStream
: Stream) : Stream * HMACSHA256 =
66 assert (key
.Length = 32)
67 let hmac = new HMACSHA256 (key
)
68 new CryptoStream (outputStream
, hmac, CryptoStreamMode.Write) :> Stream, hmac
70 let ComputeHMAC (key
: byte
[]) (inputStream
: Stream) : byte
[] =
71 assert (key
.Length = 32)
72 let hmac = new HMACSHA256 (key
)
73 hmac.ComputeHash inputStream