AES 256 -> AES 128.
[crypto_lab2.git] / labo2-fsharp / CryptoFile / Crypto.fs
1 namespace CryptoFile
2
3 open System
4 open System.IO
5 open System.Security.Cryptography
6
7 // Some cryptography primitives specific to CryptoFile.
8 module internal Crypto =
9 type Data = byte[]
10
11 let rsaKeySize = 2048
12 let aesKeySize = 128
13
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
19 result
20
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
25
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.
30
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.
35
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")
41
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)
47
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)
55
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)
63
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
69
70 let ComputeHMAC (key: byte[]) (inputStream: Stream) : byte[] =
71 assert (key.Length = 32)
72 let hmac = new HMACSHA256 (key)
73 hmac.ComputeHash inputStream