8ea0629fb0f8c732aa98afaef256316c0a07517b
5 open System.Security.Cryptography
7 // Some cryptography primitives specific to CryptoFile.
8 module internal Crypto =
14 exception KeySizeError
17 /// Returns a cryptographically strong sequence of bytes.
18 let rand size
: byte
[] =
19 let result = Array.zeroCreate
size
20 let 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
, false) // Uses PKCS#1 v1.5 padding.
34 let decryptRSA (privateKey
: Key) (cipherdata
: Data) : Data =
35 use rsa = new RSACryptoServiceProvider (rsaKeySize)
36 rsa.FromXmlString privateKey
37 rsa.Decrypt (cipherdata
, false) // Uses PKCS#1 v1.5 padding.
39 /// Produces a signature from a given hash.
40 let signRSA (privKey
: Key) (sha256
: Data) : Data =
41 use rsa = new RSACryptoServiceProvider (rsaKeySize)
42 rsa.FromXmlString privKey
43 rsa.SignHash (sha256
, CryptoConfig.MapNameToOID "SHA256")
45 /// Verify a signature against a given hash.
46 let verifySignRSA (pubKey
: Key) (sha256
: Data) (signature
: Data) : bool =
47 use rsa = new RSACryptoServiceProvider (rsaKeySize)
48 rsa.FromXmlString pubKey
49 rsa.VerifyHash (sha256
, CryptoConfig.MapNameToOID "SHA256", signature
)
51 /// Returns 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 let encryptor = aes.CreateEncryptor (key
, iv
)
57 new CryptoStream (outputStream
, encryptor, CryptoStreamMode.Write)
59 /// Returns a decrypted input stream.
60 let decryptAES (key
: byte
[]) (iv
: byte
[]) (inputStream
: Stream) : CryptoStream =
61 if key
.Length <> aesKeySize / 8 then raise
KeySizeError
62 if iv
.Length <> 16 then raise
IVSizeError
63 use aes = new AesCryptoServiceProvider (KeySize = aesKeySize)
64 let decryptor = aes.CreateDecryptor (key
, iv
)
65 new CryptoStream (inputStream
, decryptor, CryptoStreamMode.Read)
67 // Create a stream to compute the HMAC-SHA256 against all data being written.
68 let HMACStream (key
: byte
[]) (outputStream
: Stream) : Stream * HMACSHA256 =
69 if key
.Length <> 32 then raise
KeySizeError
70 let hmac = new HMACSHA256 (key
)
71 new CryptoStream (outputStream
, hmac, CryptoStreamMode.Write) :> Stream, hmac
73 let ComputeHMAC (key
: byte
[]) (inputStream
: Stream) : byte
[] =
74 if key
.Length <> 32 then raise
KeySizeError
75 let hmac = new HMACSHA256 (key
)
76 hmac.ComputeHash inputStream