Add measures and tests.
authorUmmon <greg.burri@gmail.com>
Tue, 16 Dec 2014 22:41:36 +0000 (23:41 +0100)
committerUmmon <greg.burri@gmail.com>
Tue, 16 Dec 2014 22:41:36 +0000 (23:41 +0100)
rapport/main.tex
src/RsaCrt.cpp
src/RsaCrt.h
src/RsaStd.cpp
src/RsaStd.h
src/Tests.cpp [new file with mode: 0644]
src/Tests.h [new file with mode: 0644]
src/Utils.cpp
src/Utils.h
src/lab3.qbs
src/main.cpp

index b9ab258..eeeafa4 100644 (file)
 
 
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{RSA-CRT}
+
+\subsection{Implémentation}
+
+L'implémentation utilise le langage \emph{C++11}, le compilateur \emph{GCC} 4.9.1, la \emph{library} \emph{GMP} 6.0.0 ainsi que la système de \emph{build} \emph{QBS}~\footnote{\url{http://qt-project.org/wiki/qbs}}.
+
+Le fichier \emph{*.qbs} peut-être ouvert à l'aide de \emph{Qt Creator}~\footnote{\url{http://qt-project.org/wiki/Category:Tools::QtCreator}}
+
+
+\subsubsection*{Question 1.1 : Comment s'assure-t-on que les routines implémentées fonctionnent correctement ?}
+
+Pour chaque version, standard et restes chinois, une paire de clefs est générée puis trois messages sont testés avec des valeurs différentes correspondantes à $n$, $n-1$ et $n / 2$. Pour le premier cas la vérification de la signature ne doit pas fonctionner car le message est trop grand, dans les deux autres cas, on vérifie la signature ainsi qu'une signature altérée (incrémentée de 1).
+
+Les tests peuvent être lancés avec la commande suivante :
+
+\begin{verbatim}
+qbs run -- tests 
+\end{verbatim}
+
+
+\subsubsection*{Question 1.2 : Quel est le gain en terme de temps d'exécution lors de la création d'une signature avec \emph{RSA-CRT} par rapport à la version standard ?}
+
+Les mesures sont réalisées en générant $20'000$ signatures. Vingt paires de clefs différentes sont utilisées.
+
+Les temps sont mesurés à l'aide de la commande suivante :
+
+\begin{verbatim}
+qbs run release -- time-measures 
+\end{verbatim}
+
+\begin{itemize}
+   \item \emph{RSA} standard : $14'800\, ms$ ($740\, \mu s$ par signature).
+   \item \emph{RSA CRT} : $4'466\, ms$ ($223, \mu s$ par signature).
+\end{itemize}
+
+La génération de signature avec \emph{RSA CRT} est en moyenne 3.25 fois plus rapide.
+
+
+\subsubsection*{Question 1.3 : Quels sont les valeurs que l'on peut pré-calculer est stocker hormis $n$ et $d$ afin d'améliorer la vitesse de calcul d'une signature avec \emph{RSA-CRT} ?}
 
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{L'attaque de \emph{Boneh-DeMillo-Lipton}}
+
+\subsection{Fonctionnement}
+
+(maths)
+
+\subsubsection*{Question 2.1 : En pratique, comment est-il possible d'introduire des fautes dans l'implémentation d'un algorithme cryptographique ?}
+
+\subsubsection*{Est-ce que cette attaque fonctionne dans le cas d'un bourrage non détérministe ?}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{Le \flqq truc \frqq de \emph{Shamir}}
+
+\subsection{Fonctionnement}
+
+(maths)
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \section{Conclusion}
 
 
 % http://en.wikipedia.org/wiki/RSA_%28cryptosystem%29
+
 %\bibliographystyle{plain}
 %\bibliography{main}
 
index 9e2c3c9..19bc4d7 100644 (file)
@@ -20,6 +20,7 @@ pair<Rsa::KeyPub, RsaCrt::KeyPriv> RsaCrt::generateRSAKeys(uint exponent, uint k
       kPriv.n = kPub.n = kPriv.p * kPriv.q;
       phi = (kPriv.p - 1) * (kPriv.q - 1);
 
+   // d = e^-1 (mode phi).
    } while (mpz_invert(kPriv.d.get_mpz_t(), kPub.e.get_mpz_t(), phi.get_mpz_t()) == 0);
 
    kPriv.dp = kPriv.d % (kPriv.p - 1);
index 87f9a11..2341939 100644 (file)
@@ -24,6 +24,9 @@ public:
 
    static std::pair<Rsa::KeyPub, KeyPriv> generateRSAKeys(uint exponent, uint keySizeBits);
 
+   /**
+    * m must not be greater or equal than kPriv.n.
+    */
    static mpz_class sign(const mpz_class& m, const KeyPriv& kPriv);
 };
 
index 17c2345..114fad0 100644 (file)
@@ -1,5 +1,6 @@
 #include "RsaStd.h"
 
+#include <iostream>
 using namespace std;
 
 #include "Rand.h"
@@ -20,21 +21,17 @@ pair<Rsa::KeyPub, RsaStd::KeyPriv> RsaStd::generateRSAKeys(uint exponent, uint k
       kPriv.n = kPub.n = p * q;
       phi = (p - 1) * (q - 1);
 
+   // d = e^-1 (mode phi).
    } while (mpz_invert(kPriv.d.get_mpz_t(), kPub.e.get_mpz_t(), phi.get_mpz_t()) == 0); // If 'd' is not invertible we try another primes.
 
-// For debugging purpose.
-//   Utils::print("p", p);
-//   Utils::print("q", q);
-//   Utils::print("n", kPub.n);
-//   Utils::print("phi", phi);
-//   Utils::print("d", kPriv.d);
-
    return make_pair(kPub, kPriv);
 }
 
 mpz_class RsaStd::sign(const mpz_class& m, const KeyPriv& kPriv)
 {
    mpz_class result;
+
+   // m^d (mod n).
    mpz_powm_sec(result.get_mpz_t(), m.get_mpz_t(), kPriv.d.get_mpz_t(), kPriv.n.get_mpz_t());
    return result;
 }
index ea348bf..27f73ad 100644 (file)
@@ -16,6 +16,10 @@ public:
 
    static std::pair<Rsa::KeyPub, KeyPriv> generateRSAKeys(uint exponent, uint keySizeBits);
 
+   /**
+    * Return m^d (mod n).
+    * m must not be greater or equal than kPriv.n.
+    */
    static mpz_class sign(const mpz_class& m, const KeyPriv& kPriv);
 };
 
diff --git a/src/Tests.cpp b/src/Tests.cpp
new file mode 100644 (file)
index 0000000..f45cc0c
--- /dev/null
@@ -0,0 +1,132 @@
+#include "Tests.h"
+
+#include <iostream>
+using namespace std;
+
+#include <gmpxx.h>
+
+#include "Rand.h"
+#include "RsaStd.h"
+#include "RsaCrt.h"
+
+Tests::Tests(uint keySizeBits, uint rsaPublicExponent) :
+   KEY_SIZE_BITS(keySizeBits),
+   RSA_PUBLIC_EXPONENT(rsaPublicExponent)
+{
+}
+
+void Tests::runTests()
+{
+   if (this->rsaStandard())
+      cout << "RSA standard OK" << endl;
+   else
+      cout << "RSA standard failed!" << endl;
+
+   if (this->rsaCrt())
+      cout << "RSA CRT OK" << endl;
+   else
+      cout << "RSA CRT failed!" << endl;
+}
+
+void Tests::runTimeMeasures()
+{
+   const int N = 1000;
+   const int nbKeys = 20; // Number of different generated key.
+
+   int timeRsaStd = 0;
+   int timeRsaCRT = 0;
+
+   for (int k = 0; k < nbKeys; ++k)
+   {
+      timeRsaStd += timeSignRsaStd(N);
+      timeRsaCRT += timeSignRsaCRT(N);
+   }
+
+   cout << N * nbKeys << " x RSA standard: " << timeRsaStd << " ms" << endl;
+   cout << N * nbKeys << " x RSA CRT: " << timeRsaCRT << " ms" << endl;
+   cout << "Speedup: " << (double(timeRsaStd) / double(timeRsaCRT)) << endl;
+}
+
+bool Tests::rsaStandard()
+{
+   const auto& keys = RsaStd::generateRSAKeys(RSA_PUBLIC_EXPONENT, KEY_SIZE_BITS);
+   const auto& kPub = keys.first;
+   const auto& kPriv = keys.second;
+
+   {
+      mpz_class message = kPriv.n;
+      mpz_class signature = RsaStd::sign(message, kPriv);
+      if (Rsa::verifySignature(message, signature, kPub)) // Must not be able to signe message greater than kPriv.n.
+         return false;
+   }
+
+   {
+      mpz_class message = kPriv.n - 1;
+      mpz_class signature = RsaStd::sign(message, kPriv);
+      if (!Rsa::verifySignature(message, signature, kPub) || Rsa::verifySignature(message + 1, signature, kPub))
+         return false;
+   }
+
+   {
+      mpz_class message = kPriv.n / 2;
+      mpz_class signature = RsaStd::sign(message, kPriv);
+      if (!Rsa::verifySignature(message, signature, kPub) || Rsa::verifySignature(message + 1, signature, kPub))
+         return false;
+   }
+
+   return true;
+}
+
+bool Tests::rsaCrt()
+{
+   const auto& keys = RsaCrt::generateRSAKeys(RSA_PUBLIC_EXPONENT, KEY_SIZE_BITS);
+   const auto& kPub = keys.first;
+   const auto& kPriv = keys.second;
+
+   {
+      mpz_class message = kPriv.n;
+      mpz_class signature = RsaCrt::sign(message, kPriv);
+      if (Rsa::verifySignature(message, signature, kPub)) // Must not be able to signe message greater than kPriv.n.
+         return false;
+   }
+
+   {
+      mpz_class message = kPriv.n - 1;
+      mpz_class signature = RsaCrt::sign(message, kPriv);
+      if (!Rsa::verifySignature(message, signature, kPub) || Rsa::verifySignature(message + 1, signature, kPub))
+         return false;
+   }
+
+   {
+      mpz_class message = kPriv.n / 2;
+      mpz_class signature = RsaCrt::sign(message, kPriv);
+      if (!Rsa::verifySignature(message, signature, kPub) || Rsa::verifySignature(message + 1, signature, kPub))
+         return false;
+   }
+
+   return true;
+}
+
+int Tests::timeSignRsaStd(int N)
+{
+   Timer timer;
+   const auto& keys = RsaStd::generateRSAKeys(RSA_PUBLIC_EXPONENT, KEY_SIZE_BITS);
+
+   mpz_class message = Rand::randSize(KEY_SIZE_BITS / 2);
+   for (int i = 0; i < N; i++)
+      RsaStd::sign(message, keys.second);
+
+   return timer.ms();
+}
+
+int Tests::timeSignRsaCRT(int N)
+{
+   Timer timer;
+   const auto& keys = RsaCrt::generateRSAKeys(RSA_PUBLIC_EXPONENT, KEY_SIZE_BITS);
+
+   mpz_class message = Rand::randSize(KEY_SIZE_BITS / 2);
+   for (int i = 0; i < N; i++)
+      RsaCrt::sign(message, keys.second);
+
+   return timer.ms();
+}
diff --git a/src/Tests.h b/src/Tests.h
new file mode 100644 (file)
index 0000000..4f01ac0
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef TESTS_H
+#define TESTS_H
+
+#include "Utils.h"
+
+class Tests
+{
+public:
+   Tests(uint keySizeBits, uint rsaPublicExponent);
+
+   void runTests();
+   void runTimeMeasures();
+
+private:
+   bool rsaStandard();
+   bool rsaCrt();
+
+   int timeSignRsaStd(int N);
+   int timeSignRsaCRT(int N);
+
+   const uint KEY_SIZE_BITS;
+   const uint RSA_PUBLIC_EXPONENT;
+};
+
+#endif
index 0bae372..2de443d 100644 (file)
@@ -3,11 +3,6 @@
 #include <iostream>
 using namespace std;
 
-void Utils::print(string name, mpz_class value)
-{
-   cout << name << ": " << value << endl;
-}
-
 Timer::Timer() :
    time(chrono::high_resolution_clock::now())
 {}
index 3507763..2998718 100644 (file)
@@ -7,11 +7,7 @@
 
 #include <gmpxx.h>
 
-class Utils
-{
-public:
-   static void print(std::string name, mpz_class value);
-};
+typedef unsigned int uint;
 
 class Timer
 {
index 47e20ae..2cdba34 100644 (file)
@@ -4,9 +4,9 @@ Product {
    name: "lab3"
    type: "application"
 
-   files: ["main.cpp", "Rand.h", "Rand.cpp", "Rsa.h", "Rsa.cpp", "RsaStd.h", "RsaStd.cpp", "RsaCrt.h", "RsaCrt.cpp", "Utils.h", "Utils.cpp"]
+   files: ["main.cpp", "Rand.h", "Rand.cpp", "Rsa.h", "Rsa.cpp", "RsaStd.h", "RsaStd.cpp", "RsaCrt.h", "RsaCrt.cpp", "Utils.h", "Utils.cpp", "Tests.h", "Tests.cpp"]
 
-   cpp.commonCompilerFlags: ["-std=c++14"]
+   cpp.commonCompilerFlags: ["-std=c++11"]
    cpp.staticLibraries: ["gmp", "gmpxx"]
 
    Properties {
index 9324bfc..03d1173 100644 (file)
@@ -6,81 +6,20 @@
   * Author: Grégory Burri
   */
 
+#include <vector>
 #include <iostream>
 using namespace std;
 
 #include <gmpxx.h>
 
-#include "Utils.h"
-#include "Rand.h"
-#include "Rsa.h"
-#include "RsaStd.h"
-#include "RsaCrt.h"
+#include "Tests.h"
 
 const uint KEY_SIZE_BITS = 1024;
 const uint RSA_PUBLIC_EXPONENT = 65537;
 
-bool testRsaStandard()
+void printUsage(const string& progName)
 {
-   const auto& keys = RsaStd::generateRSAKeys(RSA_PUBLIC_EXPONENT, KEY_SIZE_BITS);
-   const auto& kPub = keys.first;
-   const auto& kPriv = keys.second;
-
-   mpz_class message = Rand::randSize(KEY_SIZE_BITS / 2);
-   mpz_class signature = RsaStd::sign(message, kPriv);
-
-   return Rsa::verifySignature(message, signature, kPub) && !Rsa::verifySignature(message + 1, signature, kPub);
-}
-
-bool testRsaCrt()
-{
-   const auto& keys = RsaCrt::generateRSAKeys(RSA_PUBLIC_EXPONENT, KEY_SIZE_BITS);
-   const auto& kPub = keys.first;
-   const auto& kPriv = keys.second;
-
-   mpz_class message = Rand::randSize(KEY_SIZE_BITS / 2);
-   mpz_class signature = RsaCrt::sign(message, kPriv);
-
-   return Rsa::verifySignature(message, signature, kPub) && !Rsa::verifySignature(message + 1, signature, kPub);
-}
-
-int timeSignRsaStd(int N)
-{
-   Timer timer;
-   const auto& keys = RsaStd::generateRSAKeys(RSA_PUBLIC_EXPONENT, KEY_SIZE_BITS);
-
-   for (int i = 0; i < N; i++)
-   {
-      mpz_class message = Rand::randSize(KEY_SIZE_BITS / 2);
-      RsaStd::sign(message, keys.second);
-   }
-
-   return timer.ms();
-}
-
-int timeSignRsaCRT(int N)
-{
-   Timer timer;
-   const auto& keys = RsaCrt::generateRSAKeys(RSA_PUBLIC_EXPONENT, KEY_SIZE_BITS);
-
-   for (int i = 0; i < N; i++)
-   {
-      mpz_class message = Rand::randSize(KEY_SIZE_BITS / 2);
-      RsaCrt::sign(message, keys.second);
-   }
-
-   return timer.ms();
-}
-
-void measuresRsaDurations()
-{
-   const int N = 10000;
-   int timeRsaStd = timeSignRsaStd(N);
-   int timeRsaCRT = timeSignRsaCRT(N);
-
-   cout << N << " x RSA standard: " << timeRsaStd << " ms" << endl;
-   cout << N << " x RSA CRT: " << timeRsaCRT << " ms" << endl;
-   cout << "Speedup: " << (double(timeRsaStd) / double(timeRsaCRT)) << endl;
+   cout << "Usage: " << progName << " [tests|time-measures]" << endl;
 }
 
 int main(int argc, char** argv)
@@ -89,13 +28,12 @@ int main(int argc, char** argv)
    for (int i = 0; i < argc; i++)
       args.push_back(string(argv[i]));
 
-   if (!testRsaStandard())
-      cout << "RSA standard failed!" << endl;
-
-   if (!testRsaCrt())
-      cout << "RSA CRT failed!" << endl;
-
-   measuresRsaDurations();
+   if (args.size() >= 2 && args[1] == "tests")
+      Tests(KEY_SIZE_BITS, RSA_PUBLIC_EXPONENT).runTests();
+   else if (args.size() >= 2 && args[1] == "time-measures")
+      Tests(KEY_SIZE_BITS, RSA_PUBLIC_EXPONENT).runTimeMeasures();
+   else
+      printUsage(args[0]);
 
    return 0;
 }