12 Tests::Tests(uint keySizeBits
, uint rsaPublicExponent
) :
13 KEY_SIZE_BITS(keySizeBits
),
14 RSA_PUBLIC_EXPONENT(rsaPublicExponent
)
18 void Tests::runTests()
20 if (this->rsaStandard())
21 cout
<< "RSA standard OK" << endl
;
23 cout
<< "RSA standard failed!" << endl
;
26 cout
<< "RSA CRT OK" << endl
;
28 cout
<< "RSA CRT failed!" << endl
;
31 void Tests::runTimeMeasures()
34 const int nbKeys
= 20; // Number of different generated key.
39 for (int k
= 0; k
< nbKeys
; ++k
)
41 timeRsaStd
+= timeSignRsaStd(N
);
42 timeRsaCRT
+= timeSignRsaCRT(N
);
45 cout
<< N
* nbKeys
<< " x RSA standard: " << timeRsaStd
<< " ms" << endl
;
46 cout
<< N
* nbKeys
<< " x RSA CRT: " << timeRsaCRT
<< " ms" << endl
;
47 cout
<< "Speedup: " << (double(timeRsaStd
) / double(timeRsaCRT
)) << endl
;
50 void Tests::doAttack()
52 const auto& keys
= RsaCrt::generateRSAKeys(RSA_PUBLIC_EXPONENT
, KEY_SIZE_BITS
);
53 const auto& kPub
= keys
.first
;
54 const auto& kPriv
= keys
.second
;
55 mpz_class message
= Rand::randSize(128);
56 mpz_class faultySignature
= RsaCrt::signWithFaultySp(message
, kPriv
);
57 mpz_class correctSignature
= RsaCrt::sign(message
, kPriv
);
61 cout
<< "Original:" << endl
;
62 cout
<< " p = " << kPriv
.p
<< endl
;
63 cout
<< " q = " << kPriv
.q
<< endl
;
65 // At this point the attacker doesn't know the private key but he has intercepted the message and the faulty signature.
67 mpz_class faultySignaturePowerE
;
68 mpz_pow_ui(faultySignaturePowerE
.get_mpz_t(), faultySignature
.get_mpz_t(), RSA_PUBLIC_EXPONENT
);
69 mpz_class messageMinuxFaultySignaturePowerE
= message
- faultySignaturePowerE
;
71 mpz_gcd(q
.get_mpz_t(), messageMinuxFaultySignaturePowerE
.get_mpz_t(), kPub
.n
.get_mpz_t());
72 mpz_class p
= kPub
.n
/ q
;
74 cout
<< "Found with a faulty signature:" << endl
;
75 cout
<< " p = " << p
<< endl
;
76 cout
<< " q = " << q
<< endl
;
78 attackOK
= attackOK
&& kPriv
.p
== p
&& kPriv
.q
== q
; // With p and q we can recreate the original private key.
81 // Try the attack with a correct signature.
83 mpz_class correctSignaturePowerE
;
84 mpz_pow_ui(correctSignaturePowerE
.get_mpz_t(), correctSignature
.get_mpz_t(), RSA_PUBLIC_EXPONENT
);
85 mpz_class messageMinuxCorrectSignaturePowerE
= message
- correctSignaturePowerE
;
87 mpz_gcd(q
.get_mpz_t(), messageMinuxCorrectSignaturePowerE
.get_mpz_t(), kPub
.n
.get_mpz_t());
88 mpz_class p
= kPub
.n
/ q
;
90 cout
<< "Found with a correct signature:" << endl
;
91 cout
<< " p = " << p
<< endl
; // Equal to 1.
92 cout
<< " q = " << q
<< endl
; // Equal to n.
94 attackOK
= attackOK
&& kPriv
.p
!= p
&& kPriv
.q
!= q
;
98 cout
<< "Attack successful" << endl
;
100 cout
<< "Attack failed" << endl
;
103 bool Tests::rsaStandard()
105 const auto& keys
= RsaStd::generateRSAKeys(RSA_PUBLIC_EXPONENT
, KEY_SIZE_BITS
);
106 const auto& kPub
= keys
.first
;
107 const auto& kPriv
= keys
.second
;
110 mpz_class message
= kPriv
.n
;
111 mpz_class signature
= RsaStd::sign(message
, kPriv
);
112 if (Rsa::verifySignature(message
, signature
, kPub
)) // Must not be able to signe message greater than kPriv.n.
117 mpz_class message
= kPriv
.n
- 1;
118 mpz_class signature
= RsaStd::sign(message
, kPriv
);
119 if (!Rsa::verifySignature(message
, signature
, kPub
) || Rsa::verifySignature(message
+ 1, signature
, kPub
))
124 mpz_class message
= kPriv
.n
/ 2;
125 mpz_class signature
= RsaStd::sign(message
, kPriv
);
126 if (!Rsa::verifySignature(message
, signature
, kPub
) || Rsa::verifySignature(message
+ 1, signature
, kPub
))
135 const auto& keys
= RsaCrt::generateRSAKeys(RSA_PUBLIC_EXPONENT
, KEY_SIZE_BITS
);
136 const auto& kPub
= keys
.first
;
137 const auto& kPriv
= keys
.second
;
140 mpz_class message
= kPub
.n
;
141 mpz_class signature
= RsaCrt::sign(message
, kPriv
);
142 if (Rsa::verifySignature(message
, signature
, kPub
)) // Must not be able to signe message greater than kPub.n.
147 mpz_class message
= kPub
.n
- 1;
148 mpz_class signature
= RsaCrt::sign(message
, kPriv
);
149 if (!Rsa::verifySignature(message
, signature
, kPub
) || Rsa::verifySignature(message
+ 1, signature
, kPub
))
154 mpz_class message
= kPub
.n
/ 2;
155 mpz_class signature
= RsaCrt::sign(message
, kPriv
);
156 if (!Rsa::verifySignature(message
, signature
, kPub
) || Rsa::verifySignature(message
+ 1, signature
, kPub
))
163 int Tests::timeSignRsaStd(int N
)
166 const auto& keys
= RsaStd::generateRSAKeys(RSA_PUBLIC_EXPONENT
, KEY_SIZE_BITS
);
168 mpz_class message
= Rand::randSize(KEY_SIZE_BITS
/ 2);
169 for (int i
= 0; i
< N
; i
++)
170 RsaStd::sign(message
, keys
.second
);
175 int Tests::timeSignRsaCRT(int N
)
178 const auto& keys
= RsaCrt::generateRSAKeys(RSA_PUBLIC_EXPONENT
, KEY_SIZE_BITS
);
180 mpz_class message
= Rand::randSize(KEY_SIZE_BITS
/ 2);
181 for (int i
= 0; i
< N
; i
++)
182 RsaCrt::sign(message
, keys
.second
);