Encrypting should be OK.
authorUmmon <greg.burri@gmail.com>
Wed, 26 Nov 2014 22:12:32 +0000 (23:12 +0100)
committerUmmon <greg.burri@gmail.com>
Wed, 26 Nov 2014 22:12:32 +0000 (23:12 +0100)
.gitignore
labo2-fsharp/CryptoFile/API.fs
labo2-fsharp/CryptoFile/Crypto.fs
labo2-fsharp/CryptoFileTests/Program.fs
labo2-fsharp/CryptoFileTests/test.out [deleted file]
labo2-fsharp/CryptoFileTests/test.txt [deleted file]
rapport/main.pdf
rapport/main.tex

index 7e5f24b..3978457 100644 (file)
@@ -1,5 +1,7 @@
 bin/
 obj/
+*.pub
+*.priv
 
 # Tex
 *.log
index 2cf2167..e4a7008 100644 (file)
@@ -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
index 34d54fa..836d636 100644 (file)
@@ -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
index cc70f97..4b83072 100644 (file)
@@ -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 <in> to <out>\n\
              \tdecrypt: Decrypt a file <in> to <out>" 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"
+
 [<EntryPoint>]
 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 (file)
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 (file)
index 8318c86..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Test
\ No newline at end of file
index 5ed8b24..e097785 100644 (file)
Binary files a/rapport/main.pdf and b/rapport/main.pdf differ
index 22e7f92..526fcc9 100644 (file)
@@ -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 } ;