3ed1c5dcc2387aadb69d51879d9945f7c3f0b9ea
5 open System.Security.Cryptography
7 // Some cryptography primitives specific to 'CryptoFile'.
8 module internal Crypto =
11 let rsaKeySize = 3072 // [bit]. For encrypting and signing.
12 let aesKeySize = 128 // [bit].
14 exception KeySizeError
17 /// Return a cryptographically strong sequence of bytes.
18 let rand size
: byte
[] =
19 let result = Array.zeroCreate
size
20 use generator = new RNGCryptoServiceProvider ()
21 generator.GetBytes result
24 /// Generate a new RSA key pair: (public * private).
25 let generateRSAKeysPair () : Key * Key =
26 use rsa = new RSACryptoServiceProvider (rsaKeySize)
27 rsa.ToXmlString false, rsa.ToXmlString true
29 let encryptRSA (publicKey
: Key) (plaindata
: Data) : Data =
30 use rsa = new RSACryptoServiceProvider (rsaKeySize)
31 rsa.FromXmlString publicKey
32 rsa.Encrypt (plaindata
, true) // Use padding OAEP (PKCS#1 v2).
34 let decryptRSA (privateKey
: Key) (cipherdata
: Data) : Data =
35 use rsa = new RSACryptoServiceProvider (rsaKeySize)
36 rsa.FromXmlString privateKey
37 rsa.Decrypt (cipherdata
, true) // Use padding OAEP (PKCS#1 v2).
39 /// Produce a signature from the given data.
40 let signRSA (privKey
: Key) (data
: Data) : Data =
41 use rsa = new RSACryptoServiceProvider (rsaKeySize)
42 rsa.FromXmlString privKey
43 rsa.SignHash (data
, CryptoConfig.MapNameToOID "SHA256")
45 /// Verify a signature against the given data.
46 let verifySignRSA (pubKey
: Key) (data
: Data) (signature
: Data) : bool =
47 use rsa = new RSACryptoServiceProvider (rsaKeySize)
48 rsa.FromXmlString pubKey
49 rsa.VerifyHash (data
, CryptoConfig.MapNameToOID "SHA256", signature
)
51 /// Return an encrypted output stream.
52 let encryptAES (key
: byte
[]) (iv
: byte
[]) (outputStream
: Stream) : CryptoStream =
53 if key
.Length <> aesKeySize / 8 then raise
KeySizeError
54 if iv
.Length <> 16 then raise
IVSizeError
55 use aes = new AesCryptoServiceProvider (KeySize = aesKeySize) // Default mode is CBC.
56 new CryptoStream (outputStream
, aes.CreateEncryptor (key
, iv
), CryptoStreamMode.Write)
58 /// Return a decrypted input stream.
59 let decryptAES (key
: byte
[]) (iv
: byte
[]) (inputStream
: Stream) : CryptoStream =
60 if key
.Length <> aesKeySize / 8 then raise
KeySizeError
61 if iv
.Length <> 16 then raise
IVSizeError
62 use aes = new AesCryptoServiceProvider (KeySize = aesKeySize)
63 new CryptoStream (inputStream
, aes.CreateDecryptor (key
, iv
), CryptoStreamMode.Read)
65 /// Create a stream to compute HMAC-SHA256 against all data being written.
66 let HMACStream (key
: byte
[]) (outputStream
: Stream) : Stream * HMACSHA256 =
67 if key
.Length <> 32 then raise
KeySizeError
68 let hmac = new HMACSHA256 (key
)
69 new CryptoStream (outputStream
, hmac, CryptoStreamMode.Write) :> Stream, hmac
71 /// Compute HMAC-SHA256 for all the data in the input stream.
72 let ComputeHMAC (key
: byte
[]) (inputStream
: Stream) : byte
[] =
73 if key
.Length <> 32 then raise
KeySizeError
74 use hmac = new HMACSHA256 (key
)
75 hmac.ComputeHash inputStream