X-Git-Url: http://git.euphorik.ch/?a=blobdiff_plain;f=labo2-fsharp%2FCryptoFile%2FCrypto.fs;h=3ed1c5dcc2387aadb69d51879d9945f7c3f0b9ea;hb=57d7ae8d75a854296718cb1056efbeb476309908;hp=34d54fa68cf04673424479a57e91c095bb60c4fe;hpb=beda8d83dc421c479bdcf5ee626ec85ee8555a80;p=crypto_lab2.git diff --git a/labo2-fsharp/CryptoFile/Crypto.fs b/labo2-fsharp/CryptoFile/Crypto.fs index 34d54fa..3ed1c5d 100644 --- a/labo2-fsharp/CryptoFile/Crypto.fs +++ b/labo2-fsharp/CryptoFile/Crypto.fs @@ -1,75 +1,75 @@ namespace CryptoFile -// Some cryptography primitives specific to CryptoFile. -module internal Crypto = - open System.Security.Cryptography - open System.IO +open System +open System.IO +open System.Security.Cryptography +// Some cryptography primitives specific to 'CryptoFile'. +module internal Crypto = type Data = byte[] - let rsaKeySize = 2048 + let rsaKeySize = 3072 // [bit]. For encrypting and signing. + let aesKeySize = 128 // [bit]. + + exception KeySizeError + exception IVSizeError - /// Returns a cryptographically strong sequence of bytes. + /// Return a cryptographically strong sequence of bytes. let rand size : byte[] = let result = Array.zeroCreate size - let generator = new RNGCryptoServiceProvider () + use generator = new RNGCryptoServiceProvider () generator.GetBytes result result /// Generate a new RSA key pair: (public * private). - let generateRSAKeysPair : Key * Key = + let generateRSAKeysPair () : Key * Key = use rsa = new RSACryptoServiceProvider (rsaKeySize) - try - rsa.ToXmlString false, rsa.ToXmlString true - finally - rsa.PersistKeyInCsp <- false + rsa.ToXmlString false, rsa.ToXmlString true - let encryptRSA (publicKey : Key) (plaindata : Data) : Data = + 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 + rsa.FromXmlString publicKey + rsa.Encrypt (plaindata, true) // Use padding OAEP (PKCS#1 v2). - let decryptRSA (privateKey : Key) (cipherdata : Data) : Data = + 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 + rsa.FromXmlString privateKey + rsa.Decrypt (cipherdata, true) // Use padding OAEP (PKCS#1 v2). - /// Produces a signature from a given hash. - let signRSA (privKey : Key) (sha256 : Data) : Data = + /// Produce a signature from the given data. + let signRSA (privKey: Key) (data: Data) : Data = use rsa = new RSACryptoServiceProvider (rsaKeySize) - try - rsa.FromXmlString privKey - rsa.SignHash (sha256, CryptoConfig.MapNameToOID "SHA256") - finally - rsa.PersistKeyInCsp <- false + rsa.FromXmlString privKey + rsa.SignHash (data, CryptoConfig.MapNameToOID "SHA256") - /// Verify a signature against a given hash. - let verifySignRSA (pubKey : Key) (sha256 : Data) (signature : Data) : bool = + /// Verify a signature against the given data. + let verifySignRSA (pubKey: Key) (data: Data) (signature: Data) : bool = use rsa = new RSACryptoServiceProvider (rsaKeySize) - try - rsa.FromXmlString pubKey - rsa.VerifyHash (sha256, CryptoConfig.MapNameToOID "SHA256", signature) - finally - rsa.PersistKeyInCsp <- false + rsa.FromXmlString pubKey + rsa.VerifyHash (data, CryptoConfig.MapNameToOID "SHA256", signature) + + /// Return an encrypted output stream. + let encryptAES (key: byte[]) (iv: byte[]) (outputStream: Stream) : CryptoStream = + if key.Length <> aesKeySize / 8 then raise KeySizeError + if iv.Length <> 16 then raise IVSizeError + use aes = new AesCryptoServiceProvider (KeySize = aesKeySize) // Default mode is CBC. + new CryptoStream (outputStream, aes.CreateEncryptor (key, iv), CryptoStreamMode.Write) + + /// Return a decrypted input stream. + let decryptAES (key: byte[]) (iv: byte[]) (inputStream: Stream) : CryptoStream = + if key.Length <> aesKeySize / 8 then raise KeySizeError + if iv.Length <> 16 then raise IVSizeError + use aes = new AesCryptoServiceProvider (KeySize = aesKeySize) + new CryptoStream (inputStream, aes.CreateDecryptor (key, iv), CryptoStreamMode.Read) - /// 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 + /// Create a stream to compute HMAC-SHA256 against all data being written. + let HMACStream (key: byte[]) (outputStream: Stream) : Stream * HMACSHA256 = + if key.Length <> 32 then raise KeySizeError + let hmac = new HMACSHA256 (key) + new CryptoStream (outputStream, hmac, CryptoStreamMode.Write) :> Stream, hmac - /// 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 + /// Compute HMAC-SHA256 for all the data in the input stream. + let ComputeHMAC (key: byte[]) (inputStream: Stream) : byte[] = + if key.Length <> 32 then raise KeySizeError + use hmac = new HMACSHA256 (key) + hmac.ComputeHash inputStream \ No newline at end of file