From: Ummon Date: Wed, 26 Nov 2014 22:12:32 +0000 (+0100) Subject: Encrypting should be OK. X-Git-Url: http://git.euphorik.ch/?p=crypto_lab2.git;a=commitdiff_plain;h=137157b6dbd5efb99b486a30da6e10b0a175f530 Encrypting should be OK. --- diff --git a/.gitignore b/.gitignore index 7e5f24b..3978457 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ bin/ obj/ +*.pub +*.priv # Tex *.log diff --git a/labo2-fsharp/CryptoFile/API.fs b/labo2-fsharp/CryptoFile/API.fs index 2cf2167..e4a7008 100644 --- a/labo2-fsharp/CryptoFile/API.fs +++ b/labo2-fsharp/CryptoFile/API.fs @@ -1,20 +1,26 @@ namespace CryptoFile open System.IO -type internal Metadata (d : (string * string) list) = +type internal Metadata (d: (string * string) list) = new (stream : Stream, size: int) = let binaryReader = new BinaryReader (stream) new Metadata ([]) + member this.WriteTo (stream : Stream) = - let binaryWriter = new BinaryWriter (stream) - List.iter (fun (key : string, value : string) -> binaryWriter.Write key; binaryWriter.Write value) d + let memoryStream = new MemoryStream () // To know the serialized meta-data size before writtent them to 'stream'. + let memoryWriter = new BinaryWriter (memoryStream) + List.iter (fun (key : string, value : string) -> memoryWriter.Write key; memoryWriter.Write value) d + (new BinaryWriter (stream)).Write (int memoryStream.Length) + memoryStream.CopyTo (stream) module API = - let internal filename = "filename" - let internal creationTimeKey = "file-creation-time" + module internal MetaData = + let filename = "filename" + let creationTimeKey = "file-creation-time" let generatKeysPair : Key * Key = Crypto.generateRSAKeysPair + // Encrypt a given file let encryptFile (inputFilePath : string) (outputFilePath : string) (signaturePrivKey: Key) (cryptPubKey : Key) = let keyAES, keyMAC, iv = Crypto.rand 32, Crypto.rand 32, Crypto.rand 16 let fileInfo = new FileInfo (inputFilePath) @@ -22,24 +28,30 @@ module API = use outputStream = new FileStream (outputFilePath, FileMode.Create, FileAccess.Write) let writer = new BinaryWriter (outputStream) - ignore <| writer.Seek (8 + 32 + 256, SeekOrigin.Current) // Skips file-content-size, mac and signature. They will be written later. + writer.Seek (32 + 256, SeekOrigin.Current) |> ignore // Skips mac and signature. They will be written later. Crypto.encryptRSA cryptPubKey (Array.append keyAES <| Array.append keyMAC iv) |> writer.Write - printfn "pos: %A" outputStream.Position - - use cryptoStream = Crypto.encryptAES keyAES iv outputStream + let (hmacStream, hmac) = Crypto.HMACStream keyMAC outputStream + use cryptoStream = Crypto.encryptAES keyAES iv hmacStream let cryptoWriter = new BinaryWriter (cryptoStream) - // Write metadata. - let metaData = new Metadata ([filename, fileInfo.Name; creationTimeKey, fileInfo.CreationTimeUtc.Ticks.ToString ()]) - let metaDataStream = new MemoryStream () - metaData.WriteTo metaDataStream - cryptoWriter.Write (int metaDataStream.Length) - printfn "meta size: %A" (int metaDataStream.Length) - metaDataStream.Position <- 0L - metaDataStream.CopyTo cryptoStream + // Write the file metadata. + let metaData = new Metadata ([MetaData.filename, fileInfo.Name + MetaData.creationTimeKey, fileInfo.CreationTimeUtc.Ticks.ToString ()]) + metaData.WriteTo cryptoStream + + // Write the content of the file. + inputStream.CopyTo cryptoStream + cryptoStream.FlushFinalBlock () + + // Write the HMAC at the begining of the file. + outputStream.Position <- 0L + writer.Write hmac.Hash + + // Write the signature. + Crypto.signRSA signaturePrivKey hmac.Hash |> writer.Write () let decryptFile (sourceFilePath : string) (targetDirPath : string) (signaturePubKey: Key) (decryptPrivKey : Key) = - () + () \ No newline at end of file diff --git a/labo2-fsharp/CryptoFile/Crypto.fs b/labo2-fsharp/CryptoFile/Crypto.fs index 34d54fa..836d636 100644 --- a/labo2-fsharp/CryptoFile/Crypto.fs +++ b/labo2-fsharp/CryptoFile/Crypto.fs @@ -2,8 +2,9 @@ // Some cryptography primitives specific to CryptoFile. module internal Crypto = - open System.Security.Cryptography + open System open System.IO + open System.Security.Cryptography type Data = byte[] @@ -24,7 +25,7 @@ module internal Crypto = finally rsa.PersistKeyInCsp <- false - let encryptRSA (publicKey : Key) (plaindata : Data) : Data = + let encryptRSA (publicKey: Key) (plaindata: Data) : Data = use rsa = new RSACryptoServiceProvider (rsaKeySize) try rsa.FromXmlString publicKey @@ -32,7 +33,7 @@ module internal Crypto = finally rsa.PersistKeyInCsp <- false - let decryptRSA (privateKey : Key) (cipherdata : Data) : Data = + let decryptRSA (privateKey: Key) (cipherdata: Data) : Data = use rsa = new RSACryptoServiceProvider (rsaKeySize) try rsa.FromXmlString privateKey @@ -41,7 +42,7 @@ module internal Crypto = rsa.PersistKeyInCsp <- false /// Produces a signature from a given hash. - let signRSA (privKey : Key) (sha256 : Data) : Data = + let signRSA (privKey: Key) (sha256: Data) : Data = use rsa = new RSACryptoServiceProvider (rsaKeySize) try rsa.FromXmlString privKey @@ -50,7 +51,7 @@ module internal Crypto = rsa.PersistKeyInCsp <- false /// Verify a signature against a given hash. - let verifySignRSA (pubKey : Key) (sha256 : Data) (signature : Data) : bool = + let verifySignRSA (pubKey: Key) (sha256: Data) (signature: Data) : bool = use rsa = new RSACryptoServiceProvider (rsaKeySize) try rsa.FromXmlString pubKey @@ -59,17 +60,34 @@ module internal Crypto = rsa.PersistKeyInCsp <- false /// Returns an encrypted output stream. - let encryptAES (key : byte[]) (iv : byte[]) (outputStream : Stream) : Stream = + let encryptAES (key: byte[]) (iv: byte[]) (outputStream: Stream) : CryptoStream = 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 + new CryptoStream (outputStream, encryptor, CryptoStreamMode.Write) /// Returns a decrypted input stream. - let decryptAES (key : byte[]) (iv : byte[]) (inputStream : Stream) : Stream = + let decryptAES (key: byte[]) (iv: byte[]) (inputStream: Stream) : CryptoStream = 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 + new CryptoStream (inputStream, decryptor, CryptoStreamMode.Read) + + let HMACStream (key: byte[]) (outputStream: Stream) : Stream * HMACSHA256 = + assert (key.Length = 32) + let hmac = new HMACSHA256 (key) + new CryptoStream (outputStream, hmac, CryptoStreamMode.Write) :> Stream, hmac + + (*type HMACStream (buffer: byte[], output: Stream) = + inherit Stream () + override this.CanRead with get () = false + override this.CanSeek with get () = false + override this.CanWrite with get () = true + override this.Length with get () = raise <| new NotSupportedException () + override this.Position with get () = raise <| new NotSupportedException () + and set _ = raise <| new NotSupportedException () + override this.Flush () = + output.Flush () + override this.Read (_: byte[], _: int, _: int) = raise <| new NotSupportedException ()*) \ No newline at end of file diff --git a/labo2-fsharp/CryptoFileTests/Program.fs b/labo2-fsharp/CryptoFileTests/Program.fs index cc70f97..4b83072 100644 --- a/labo2-fsharp/CryptoFileTests/Program.fs +++ b/labo2-fsharp/CryptoFileTests/Program.fs @@ -1,6 +1,7 @@ -module Labo2.Main +module CryptoFileTests.Main open System +open System.IO; open CryptoFile let printUsage () = @@ -9,12 +10,34 @@ let printUsage () = \tencrypt: Encrypt a file to \n\ \tdecrypt: Decrypt a file to " System.AppDomain.CurrentDomain.FriendlyName +// Module to store and retreive the keys to and from a file. +// The private keys are stored in plain file! Do not let anyone access these files! +module internal Keys = + // Try to read the public key and private key from files. If one of a file doesn't exist + // a new key pair is created, stored the returned. + let getKey (filenamePub: string) (filenamePriv: string) : Key * Key = + try + use srPub = new StreamReader (filenamePub) + use srPriv = new StreamReader (filenamePriv) + srPub.ReadToEnd (), srPriv.ReadToEnd () + with + | _ -> + use swPub = new StreamWriter (filenamePub) + use swPriv = new StreamWriter (filenamePriv) + let keySigPub, keySigPriv = API.generatKeysPair + swPub.Write keySigPub + swPriv.Write keySigPriv + keySigPub, keySigPriv + + let getSig : Key * Key = getKey "keys-sign.pub" "keys-sign.priv" + let getCrypt : Key * Key = getKey "keys-crypt.pub" "keys-crypt.priv" + [] let main args = printfn "Labo n°2" - let keySigPub, keySigPriv = API.generatKeysPair - let keyCryptPub, keyCryptPriv = API.generatKeysPair + let keySigPub, keySigPriv = Keys.getSig + let keyCryptPub, keyCryptPriv = Keys.getCrypt match args with | [| "tests" |] -> Tests.runAllTests () diff --git a/labo2-fsharp/CryptoFileTests/test.out b/labo2-fsharp/CryptoFileTests/test.out deleted file mode 100644 index 8f31261..0000000 Binary files a/labo2-fsharp/CryptoFileTests/test.out and /dev/null differ diff --git a/labo2-fsharp/CryptoFileTests/test.txt b/labo2-fsharp/CryptoFileTests/test.txt deleted file mode 100644 index 8318c86..0000000 --- a/labo2-fsharp/CryptoFileTests/test.txt +++ /dev/null @@ -1 +0,0 @@ -Test \ No newline at end of file diff --git a/rapport/main.pdf b/rapport/main.pdf index 5ed8b24..e097785 100644 Binary files a/rapport/main.pdf and b/rapport/main.pdf differ diff --git a/rapport/main.tex b/rapport/main.tex index 22e7f92..526fcc9 100644 --- a/rapport/main.tex +++ b/rapport/main.tex @@ -50,7 +50,7 @@ mutable, if, then, else, cloud, async, static, use, abstract, interface, inherit \begin{itemize} \item \emph{RSA-2048} pour la signature ainsi que pour le chiffrage des clefs \emph{AES} et \emph{HMAC}. Le padding \emph{PKCS\#1 v1.5} est utilisé ; \item \emph{HMAC-SHA256} pour la vérification de l'intégrité ; - \item \emph{AES-CBC256} pour le chiffrement symétrique du contenu du fichier et des méta-données. + \item \emph{AES-CBC256} pour le chiffrement symétrique du contenu du fichier et des méta-données associées. Le padding \emph{PKCS7} est utilisé. \end{itemize} @@ -61,7 +61,7 @@ Le format est définit comme suit en \emph{EBNF}. Les valeurs entre crochets cor \begin{lstlisting}[frame=single, breaklines, basicstyle=\ttfamily\footnotesize] container = header, ciphertext ; -header = file-content-size[int64], mac[256], signature[2048], keys[2048] ; +header = mac[256], signature[2048], keys[2048] ; ciphertext = AES(plaintext) ; plaintext = meta-data, file-content ; meta-data = meta-data-size[int32], { key-value-pair } ;