From: Ummon Date: Fri, 28 Nov 2014 07:44:46 +0000 (+0100) Subject: Report almost done. X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=19a9446e4042d5e451f1ae0534ffba242d33879e;p=crypto_lab2.git Report almost done. --- diff --git a/labo2-fsharp/CryptoFile/API.fs b/labo2-fsharp/CryptoFile/API.fs index 0014c1e..1601c97 100644 --- a/labo2-fsharp/CryptoFile/API.fs +++ b/labo2-fsharp/CryptoFile/API.fs @@ -1,31 +1,35 @@ namespace CryptoFile + +open System open System.IO +// To read and write metadata. type internal Metadata (d: (string * string) list) = + // Read metadata from a stream. new (stream : Stream) = let reader = new BinaryReader (stream) let length = reader.ReadByte () |> int new Metadata ([for i in 1..length -> reader.ReadString (), reader.ReadString ()]) + // Write metadata to a stream. + member this.WriteTo (stream : Stream) = + let writer = new BinaryWriter (stream) + writer.Write (byte d.Length) + List.iter (fun (key : string, value : string) -> writer.Write key; writer.Write value) d + // May raise 'KeyNotFoundException'. member this.get (key: string) : string = List.pick (function | (k, v) when k = key -> Some (v) | _ -> None) d - member this.WriteTo (stream : Stream) = - let writer = new BinaryWriter (stream) - writer.Write (byte d.Length) - List.iter (fun (key : string, value : string) -> writer.Write key; writer.Write value) d - module API = module internal Metadata = - let filename = "filename" - let creationTimeKey = "file-creation-time" + let filenameKey = "filename" + let modificationTimeKey = "file-modification-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) @@ -37,13 +41,14 @@ module API = Crypto.encryptRSA cryptPubKey (Array.append keyAES <| Array.append keyMAC iv) |> writer.Write + // Plaintext -> cryptoStream -> hmacStream -> cyphertext. let (hmacStream, hmac) = Crypto.HMACStream keyMAC outputStream use cryptoStream = Crypto.encryptAES keyAES iv hmacStream let cryptoWriter = new BinaryWriter (cryptoStream) // Write the file metadata. - let metaData = new Metadata ([Metadata.filename, fileInfo.Name - Metadata.creationTimeKey, fileInfo.CreationTimeUtc.Ticks.ToString ()]) + let metaData = new Metadata ([Metadata.filenameKey, fileInfo.Name + Metadata.modificationTimeKey, fileInfo.LastWriteTimeUtc.Ticks.ToString ()]) metaData.WriteTo cryptoStream // Write the content of the file. @@ -56,7 +61,6 @@ module API = // Write the signature. Crypto.signRSA signaturePrivKey hmac.Hash |> writer.Write - () let decryptFile (sourceFilePath : string) (targetDirPath : string) (signaturePubKey: Key) (decryptPrivKey : Key) = use inputStream = new FileStream (sourceFilePath, FileMode.Open, FileAccess.Read) @@ -82,8 +86,10 @@ module API = use cryptoStream = Crypto.decryptAES keyAES iv inputStream let metadata = new Metadata (cryptoStream) - // Create the file and write. - let filename = metadata.get Metadata.filename - use outputStream = new FileStream (Path.Combine (targetDirPath, filename), FileMode.Create, FileAccess.Write) - cryptoStream.CopyTo outputStream - () + // Create the file and write its content and metadata. + let filePath = Path.Combine (targetDirPath, metadata.get Metadata.filenameKey) + let modificationTime = new DateTime (metadata.get Metadata.modificationTimeKey |> int64) + let fileInfo = new FileInfo (filePath) + using (fileInfo.Create ()) <| fun outputStream -> cryptoStream.CopyTo outputStream + fileInfo.LastWriteTimeUtc <- modificationTime + \ No newline at end of file diff --git a/labo2-fsharp/CryptoFile/Crypto.fs b/labo2-fsharp/CryptoFile/Crypto.fs index 60f9c5f..24cebd0 100644 --- a/labo2-fsharp/CryptoFile/Crypto.fs +++ b/labo2-fsharp/CryptoFile/Crypto.fs @@ -1,11 +1,11 @@ namespace CryptoFile +open System +open System.IO +open System.Security.Cryptography + // Some cryptography primitives specific to CryptoFile. module internal Crypto = - open System - open System.IO - open System.Security.Cryptography - type Data = byte[] let rsaKeySize = 2048 diff --git a/labo2-fsharp/CryptoFile/Types.fs b/labo2-fsharp/CryptoFile/Types.fs index fe72c06..38457be 100644 --- a/labo2-fsharp/CryptoFile/Types.fs +++ b/labo2-fsharp/CryptoFile/Types.fs @@ -2,7 +2,5 @@ type Key = string // For public and private RSA keys. -exception FileNotFound -exception IOError exception IntegrityError exception SignatureMismatch diff --git a/labo2-fsharp/CryptoFileTests/Program.fs b/labo2-fsharp/CryptoFileTests/Program.fs index 4b83072..b824912 100644 --- a/labo2-fsharp/CryptoFileTests/Program.fs +++ b/labo2-fsharp/CryptoFileTests/Program.fs @@ -34,8 +34,6 @@ module internal Keys = [] let main args = - printfn "Labo n°2" - let keySigPub, keySigPriv = Keys.getSig let keyCryptPub, keyCryptPriv = Keys.getCrypt @@ -45,3 +43,4 @@ let main args = | [| "decrypt"; input; outputDir |] -> API.decryptFile input outputDir keySigPub keyCryptPriv | _ -> printUsage () 0 + \ No newline at end of file diff --git a/labo2-fsharp/plaintext.txt b/labo2-fsharp/plaintext.txt new file mode 100644 index 0000000..9e6f6b6 --- /dev/null +++ b/labo2-fsharp/plaintext.txt @@ -0,0 +1,3 @@ +Violence is the last refuge of the incompetent. + - Isaac Asimov + \ No newline at end of file diff --git a/labo2-fsharp/run_tests.sh b/labo2-fsharp/run_tests.sh new file mode 100755 index 0000000..3f42fa2 --- /dev/null +++ b/labo2-fsharp/run_tests.sh @@ -0,0 +1,19 @@ +#/usr/bin/env bash +xbuild /p:Configuration=Release labo2-fsharp.sln + +echo "Plaintext:" +cat plaintext.txt +echo + +# Encrypt the file 'plaintext.txt'. +CryptoFileTests/bin/Release/CryptoFileTests.exe encrypt plaintext.txt ciphertext + +# Decrypt the file 'ciphertext' to the directory 'output'. +rm -r output +mkdir output +CryptoFileTests/bin/Release/CryptoFileTests.exe decrypt ciphertext output + +echo "Decrypted ciphertext:" +cat output/plaintext.txt +echo + diff --git a/rapport/main.tex b/rapport/main.tex index 03a7642..1c25220 100644 --- a/rapport/main.tex +++ b/rapport/main.tex @@ -11,6 +11,10 @@ \usepackage{upquote} \usepackage{color} +%%% URLs %%% +\urldef{\dotnetcrypto}\url{http://msdn.microsoft.com/en-us/library/System.Security.Cryptography%28v=vs.110%29.aspx} +\urldef{\monodevelop}\url{http://www.monodevelop.com/} + \title{ICR - Labo \#2 : \textit{Conception et implémentation d'un container sécurisé pour des données médicales}} \author{G.Burri} @@ -45,12 +49,66 @@ mutable, if, then, else, cloud, async, static, use, abstract, interface, inherit %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Introduction} +Le but de ce laboratoire est de définir les algorithmes cryptographique et leurs paramètres afin de sécuriser des données médicales. Une donnée médicale est représentée par un fichier qui devra être sécurisé au sein d'un container dont le format sera définit par nos soins. Une implémentation sera ensuite proposée. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Niveaux de sécurité} + +\subsection{Quel est le niveau de sécurité que l'on souhaite atteindre ?} + +\begin{itemize} + \item Confidentialité : les données chiffrées ne doivent pas pouvoir être décryptées par un attaquant. + \item Authenticité : un attaquant ne doit pas pouvoir forger un container, une signature est réalisée à l'aide d'une paire de clef \emph{RSA} publique-privée. + \item Intégrité : il ne faut pas que les données chiffrées aient pu être altérées par un attaquant. +\end{itemize} + + +\subsection{Comment s'assure-t-on que les données sont stockées de manière confidentielle ? En particulier ce qui concerne les méta-données} + +Les méta-données ainsi que les données sont chiffrées ensemble. Voir le format du container décrit ci après. + + +\subsection{Comment s'assure-t-on que les données stockées sont authentiques ? Quels sont les risques à prendre en compte ?} + +L'empreinte des données est signée à l'aide d'une clef privée donnée en paramètre de l'\emph{API}, ceci représente la signature qui est placée dans le container. Lors du déchiffrement, la clef publique correspondante est fournie puis utilisée pour déchiffrer l'empreinte qui est comparée à l'empreinte des données. + + +\subsection{Comment s'assure-t-on que les données stockées sont intègres ?} + +Cela est réalisé avec un \emph{MAC}, dans notre cas nous utilisons \emph{HMAC-SHA256} sur l'ensemble des données chiffrées (\emph{Encrypt-then-MAC}). + + +\subsection{Quels sont les clefs cryptographiques requises qu'il est nécessaire de gérer ?} + +\subsubsection{Clefs externes} + +Concerne les clefs externes à l'\emph{API}. + +\begin{itemize} + \item Une paire de clefs \emph{RSA-2048} pour la signature. + \item Une paire de clefs \emph{RSA-2048} pour le chiffrement des clefs \emph{AES}. +\end{itemize} + + +\subsubsection{Clefs internes} + +Concerne les clefs gérées à l'intérieur du container. + +\begin{itemize} + \item Une clef de 256 bits pour \emph{AES}. + \item Une clef de 256 bits pour \emph{HMAC}. +\end{itemize} + +Ces clefs sont générées aléatoirement à chaque création d'un container. + + \section{Choix des algorithmes et des paramètres} \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{RSA-2048} pour la signature ainsi que pour le chiffrage des clefs \emph{AES} et \emph{HMAC}. Le bourrage \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 associées. Le padding \emph{PKCS7} est utilisé. + \item \emph{AES-CBC256} pour le chiffrement symétrique du contenu du fichier et des méta-données associées. Le bourrage \emph{PKCS7} est utilisé. \end{itemize} @@ -134,61 +192,73 @@ Ce processus nécessite deux cycles de lecture des données, le premier pour le %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Implémentation} -\subsection{Utilisation} +Nous utilisons ici la plate-forme \emph{.NET} ainsi que le langage \emph{F\#}. L'ensemble des éléments cryptographiques requis sont fournit par \emph{.NET}\footnote{\dotnetcrypto}. -\subsection{Organisation du code} - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\section{Niveaux de sécurité} - -\subsection{Quel est le niveau de sécurité que l'on souhaite atteindre ?} +Deux \emph{assemblies} sont crées : \begin{itemize} - \item Confidentialité : les données chiffrées ne doivent pas pouvoir être décryptées par un attaquant. - \item Authentification : un attaquant ne doit pas pouvoir forger un container, une signature est réalisée à l'aide d'une paire de clef publique-privée. - \item Intégrité : il ne faut pas que les données chiffrées aient pu être altérées par un attaquant. + \item \emph{CryptoFile} : \emph{Library} mettant à disposition l'\emph{API} de chiffrement de fichier et de déchiffrement de container. + \item \emph{CryptoFileTests} : Exécutable utilisant la \emph{Library} \emph{CryptoFile} et permettant d'utiliser l'\emph{API} à l'aide d'arguments fournis. \end{itemize} +\subsection{Utilisation} -\subsection{Comment s'assure-t-on que les données sont stockées de manière confidentielle ? En particulier ce qui concerne les méta-données} +Il est possible de compiler la solution à l'aide de \emph{MonoDevelop}\footnote{\monodevelop}. Le script \emph{Bash} \texttt{labo2-fsharp/run\_tests.sh} montre un exemple de compilation à la ligne de commande, puis de chiffrement d'un fichier suivit du déchiffrement du container ainsi créé. -Les méta-données ainsi que les données sont chiffrées ensemble. Voir le format du container décrit précédemment. +À partir du dossier \texttt{labo2-fsharp} et après avoir compiler en \emph{release} la solution, voici ce qu'il est possible d'effectuer : +\begin{itemize} + \item \texttt{CryptoFileTests/bin/Release/CryptoFileTests.exe tests} : Réalise un série de tests. + \item \texttt{CryptoFileTests/bin/Release/CryptoFileTests.exe encrypt } : Chiffre le fichier \texttt{} ver le container \texttt{}. + \item \texttt{CryptoFileTests/bin/Release/CryptoFileTests.exe decrypt } : Déchiffre le container \texttt{} dans le dossier \texttt{}. +\end{itemize} -\subsection{Comment s'assure-t-on que les données stockées sont authentiques ? Quels sont les risques à prendre en compte ?} +Les clefs publiques et privées pour le chiffrement ainsi que pour la réalisation de la signature se trouvent dans les fichiers \texttt{keys-crypt.priv}, \texttt{keys-crypt.pub}, \texttt{keys-sign.priv} et \texttt{keys-sign.pub}. Ceux-ci sont automatiquement générés dans le cas où ils sont introuvables. -L'empreinte des données est signée à l'aide d'une clef privée donnée en paramètre de l'\emph{API}, ceci représente la signature qui est placée dans le container. Lors du déchiffrement, la clef publique correspondante est donnée puis utilisée pour déchiffrer l'empreinte qui est comparée à l'empreinte des données. +\subsection{Organisation du code} -\subsection{Comment s'assure-t-on que les données stockées sont intègres ?} +La \emph{ĺibrary} \emph{CryptoFile} est composé de trois fichiers : -Cela est réalisé avec un \emph{MAC}, dans notre nous utilisons \emph{HMAC-SHA256} sur les données chiffrées (\emph{Encrypt-then-MAC}). +\begin{itemize} + \item \emph{Types.fs} : Quelques types publics. + \item \emph{Crypto.fs} : Contient toutes les primitives cryptographique nécessaire. + \item \emph{Tests.fs} : Contient quelques tests unitaires du module \emph{Crypto}. + \item \emph{API.fs} : Contient l'interface publique de la \emph{library}. Elle est détaillée ci après. +\end{itemize} +\subsubsection{API} + +\begin{lstlisting}[language=FSharp, frame=single, basicstyle=\ttfamily\footnotesize] +module API = + let generatKeysPair : Key * Key + + let encryptFile (inputFilePath : string) + (outputFilePath : string) + (signaturePrivKey: Key) + (cryptPubKey : Key) + + let decryptFile (sourceFilePath : string) + (targetDirPath : string) + (signaturePubKey: Key) + (decryptPrivKey : Key) +\end{lstlisting} -\subsection{Quels sont les clefs cryptographiques requises qu'il est nécessaire de gérer ?} -\subsubsection{Clefs externes} -Concerne les clefs externes à l'\emph{API}. +17 Mo de mémoire et 19 s pour chiffrer un fichier de 404 Mo -\begin{itemize} - \item Une paire de clefs \emph{RSA-2048} pour la signature. - \item Une paire de clefs \emph{RSA-2048} pour le chiffrement des clefs \emph{AES}. -\end{itemize} -\subsubsection{Clefs internes} +\section{Analyse de la sécurité de l'implémentation} -Concerne les clefs gérer à l'intérieur du container. +\subsection{Quelles sont les parties critiques du code ?} -\begin{itemize} - \item Une clef de 256 bits pour \emph{AES}. - \item Une clef de 256 bits pour \emph{HMAC}. -\end{itemize} +\subsection{Comment s'est-on assuré que ces parties soient correctement implémentées ?} +\subsection{Quels sont les points-faibles restants ?} -17 Mo de mémoire et 19 s pour chiffrer un fichier de 404 Mo +\subsection{Quels sont les possibilités pour corriger ces points faibles ?} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/template.bt b/template.bt new file mode 100644 index 0000000..8ff158b --- /dev/null +++ b/template.bt @@ -0,0 +1,7 @@ +typedef struct { + UBYTE mac[32] ; + UBYTE signature[256] ; + UBYTE key[256] ; +} Header; + +Header header;