72
|
1 |
/*
|
|
2 |
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
3 |
* All rights reserved.
|
|
4 |
* This component and the accompanying materials are made available
|
|
5 |
* under the terms of the License "Eclipse Public License v1.0"
|
|
6 |
* which accompanies this distribution, and is available
|
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
8 |
*
|
|
9 |
* Initial Contributors:
|
|
10 |
* Nokia Corporation - initial contribution.
|
|
11 |
*
|
|
12 |
* Contributors:
|
|
13 |
*
|
|
14 |
* Description:
|
|
15 |
*
|
|
16 |
*/
|
|
17 |
|
|
18 |
|
|
19 |
/**
|
|
20 |
@file
|
|
21 |
*/
|
|
22 |
|
|
23 |
#include "modarith.h"
|
|
24 |
#include "nbtheory.h"
|
|
25 |
#include <iostream.h>
|
|
26 |
|
|
27 |
USING_NAMESPACE(CryptoPP)
|
|
28 |
|
|
29 |
void CheckEPOCDecrypt(Integer& e, Integer& p, Integer& q, Integer& cipher, Integer& expectedPlaintext);
|
|
30 |
|
|
31 |
void TestRSASigning()
|
|
32 |
{
|
|
33 |
const Integer m("AA36ABCE88ACFDFF55523C7FC4523F90EFA00DF3774A259F2E62B4C5D99CB5ADB300A0285E5301930E0C70FB6876939CE616CE624A11E0086D341EBCACA0A1F5h");
|
|
34 |
const Integer d("0A033748626487695F5F30BC38B98B44C2CD2DFF434098CD20D8A138D090BF64797C3FA7A2CDCB3CD1E0BDBA2654B4F9DF8E8AE59D733D9F33B301624AFD1D51h");
|
|
35 |
const Integer e(17);
|
|
36 |
|
|
37 |
// Take EPOC padded plain text, sign and verify
|
|
38 |
const Integer plain("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0054859B342C49EA2Ah");
|
|
39 |
const Integer expectedSig("786C08484F59280886A19919BECA53711819B2D2DD82D702E2F6DE991DC89CB968C01B1315A742B5BE783A781B5B1286F46DAFE29DE675C64A3BA4781DEF8F19h");
|
|
40 |
|
|
41 |
// Private Encrypt (Sign) signedText = (digest ^ d) mod m
|
|
42 |
Integer cipher_privateEncrypt = a_exp_b_mod_c(plain, d, m);
|
|
43 |
assert(cipher_privateEncrypt==expectedSig);
|
|
44 |
|
|
45 |
// Public Decrypt (Decrypt) = (signedText ^ e) mod m
|
|
46 |
Integer verified = a_exp_b_mod_c(cipher_privateEncrypt, e, m);
|
|
47 |
assert(verified==plain);
|
|
48 |
|
|
49 |
// Now reverse operations (as in previous bugged asymmetric) and check results...
|
|
50 |
// Do a private decrypt for bad signing
|
|
51 |
Integer badSign = a_exp_b_mod_c(plain, d, m);
|
|
52 |
assert(badSign==expectedSig);
|
|
53 |
|
|
54 |
// And verify (public encryption)
|
|
55 |
Integer badVerify = a_exp_b_mod_c(badSign, e, m);
|
|
56 |
assert(badVerify==plain);
|
|
57 |
|
|
58 |
}
|
|
59 |
|
|
60 |
void TestRSADecryptValues()
|
|
61 |
{
|
|
62 |
// First test a good set
|
|
63 |
/* <modulus>BBF82F090682CE9C2338AC2B9DA871F7368D07EED41043A440D6B6F07454F51FB8DFBAAF035C02AB61EA48CEEB6FCD4876ED520D60E1EC4619719D8A5B8B807FAFB8E0A3DFC737723EE6B4B7D93A2584EE6A649D060953748834B2454598394EE0AAB12D7B61A51F527A9A41F6C1687FE2537298CA2A8F5946F8E5FD091DBDCB</modulus>
|
|
64 |
<P>EECFAE81B1B9B3C908810B10A1B5600199EB9F44AEF4FDA493B81A9E3D84F632124EF0236E5D1E3B7E28FAE7AA040A2D5B252176459D1F397541BA2A58FB6599</P>
|
|
65 |
<Q>C97FB1F027F453F6341233EAAAD1D9353F6C42D08866B1D05A0F2035028B9D869840B41666B42E92EA0DA3B43204B5CFCE3352524D0416A5A441E700AF461503</Q>
|
|
66 |
<dP>54494CA63EBA0337E4E24023FCD69A5AEB07DDDC0183A4D0AC9B54B051F2B13ED9490975EAB77414FF59C1F7692E9A2E202B38FC910A474174ADC93C1F67C981</dP>
|
|
67 |
<dQ>471E0290FF0AF0750351B7F878864CA961ADBD3A8A7E991C5C0556A94C3146A7F9803F8F6F8AE342E931FD8AE47A220D1B99A495849807FE39F9245A9836DA3D</dQ>
|
|
68 |
<qInv>B06C4FDABB6301198D265BDBAE9423B380F271F73453885093077FCD39E2119FC98632154F5883B167A967BF402B4E9E2E0F9656E698EA3666EDFB25798039F7</qInv>
|
|
69 |
<plaintext>D436E99569FD32A7C8A05BBC90D32C49</plaintext>
|
|
70 |
<ciphertext>4B9C35BC3CA99B3908EF91C91F4D661544B5462CB3079D7B7A610B90039602F080417B049B7F31BAF16A87B59986620EC1BBD791AD30774309C05F0AFA24B0BF1EA1FEAA3A8EFA2C24F5626B8A9C9A157C1018DA54D314E728E2DB75E84FB5E99082561D904139B95C4DA70A5AB6412527B97CEDA04C6FB00BE1E44537706FF2</ciphertext>
|
|
71 |
*/
|
|
72 |
Integer e1 = Integer(17);
|
|
73 |
Integer p1 = Integer("EECFAE81B1B9B3C908810B10A1B5600199EB9F44AEF4FDA493B81A9E3D84F632124EF0236E5D1E3B7E28FAE7AA040A2D5B252176459D1F397541BA2A58FB6599h");
|
|
74 |
Integer q1 = Integer("C97FB1F027F453F6341233EAAAD1D9353F6C42D08866B1D05A0F2035028B9D869840B41666B42E92EA0DA3B43204B5CFCE3352524D0416A5A441E700AF461503h");
|
|
75 |
Integer cipher1 = Integer("4B9C35BC3CA99B3908EF91C91F4D661544B5462CB3079D7B7A610B90039602F080417B049B7F31BAF16A87B59986620EC1BBD791AD30774309C05F0AFA24B0BF1EA1FEAA3A8EFA2C24F5626B8A9C9A157C1018DA54D314E728E2DB75E84FB5E99082561D904139B95C4DA70A5AB6412527B97CEDA04C6FB00BE1E44537706FF2h");
|
|
76 |
Integer ePlaintext1 = Integer("D436E99569FD32A7C8A05BBC90D32C49h");
|
|
77 |
|
|
78 |
CheckEPOCDecrypt(e1, p1, q1, cipher1, ePlaintext1);
|
|
79 |
|
|
80 |
// Now test a bad set
|
|
81 |
/*
|
|
82 |
<input>123456789ABCDEF123456789ABCDEF</input>
|
|
83 |
<P>ED49CE92ABF0509006E412AC7F28EEA7626107C3F2456FA18E6513153D6F6003</P>
|
|
84 |
<Q>ED12B5B118CBA1154DC24AE05AAB1E3A33B5E47A3715861697498824E5BCA331</Q>
|
|
85 |
----------- e -----------
|
|
86 |
01 00 01
|
|
87 |
----------- P -----------
|
|
88 |
ed 49 ce 92 ab f0 50 90 06 e4 12 ac 7f 28 ee a7 62 61 07 c3 f2 45 6f a1 8e 65 13 15 3d 6f 60 03
|
|
89 |
----------- Q -----------
|
|
90 |
ed 12 b5 b1 18 cb a1 15 4d c2 4a e0 5a ab 1e 3a 33 b5 e4 7a 37 15 86 16 97 49 88 24 e5 bc a3 31
|
|
91 |
----------- DP -----------
|
|
92 |
dc e0 33 15 7c 4e f9 ee d7 3b 3d d6 ab 97 22 6f 54 b8 15 4e 64 1a 16 4b 40 0c fd b2 6b b9 5c 99
|
|
93 |
----------- DQ -----------
|
|
94 |
27 65 a3 92 11 a7 cd 56 27 fc f0 ca 85 e6 c7 f8 2e 1d bd 21 5e 44 12 6b 70 aa c4 98 35 21 7b 11
|
|
95 |
----------- QInv -----------
|
|
96 |
76 2f 0a 8c fa 16 d8 a6 df 53 0b 1c fa 5f ff 4c 55 a4 4f 52 e1 b6 28 89 1f c9 c9 10 1c d9 73 2d
|
|
97 |
----------- N -----------
|
|
98 |
db be ab d7 a5 8e c2 a8 83 17 83 86 9a 2e 07 12 03 1a 5c 0f 87 a8 4b d3 fe 3c 21 91 df 49 4e 2b e4 fa 8d a8 65 e5 c8 c7 49 4d fa c5 5c 6a d2 fc e6 96 2e 3b de 1b 38 28 94 93 04 47 dd a7 49 93
|
|
99 |
----------- ciphertext -----------
|
|
100 |
69 3a 72 26 39 cc 70 9c 89 ac dc 24 8c 52 ef 01 dd f7 5a c3 8e bf f9 8d eb ed 25 5e 11 f0 d9 b1 43 de 14 97 d2 34 65 a6 2c 11 13 6e f8 c4 37 81 01 d5 8e 8d ea 0b 33 f2 9f e2 df 68 c4 c7 34 2c
|
|
101 |
|
|
102 |
*/
|
|
103 |
// Two primes: p, q
|
|
104 |
Integer e2 = Integer(65537);
|
|
105 |
Integer p2 = Integer("ED49CE92ABF0509006E412AC7F28EEA7626107C3F2456FA18E6513153D6F6003h");
|
|
106 |
Integer q2 = Integer("ED12B5B118CBA1154DC24AE05AAB1E3A33B5E47A3715861697498824E5BCA331h");
|
|
107 |
Integer cipher2 = Integer("693A722639CC709C89ACDC248C52EF01DDF75AC38EBFF98DEBED255E11F0D9B143DE1497D23465A62C11136EF8C4378101D58E8DEA0B33F29FE2DF68C4C7342Ch");
|
|
108 |
Integer ePlaintext2 = Integer("123456789ABCDEF123456789ABCDEFh");
|
|
109 |
|
|
110 |
CheckEPOCDecrypt(e2, p2, q2, cipher2, ePlaintext2);
|
|
111 |
|
|
112 |
/*
|
|
113 |
<modulus>EF6419DC54EC49B7D0524BA675727F6D895A66A9940F3C76B6220A5B9073357D70702C9FC2D6ECA41448356CE562F7FFAF1DA64BA947274BA0D372F5866B69CB</modulus>
|
|
114 |
<P>FB4F79F4E8C816B816A817120901AED45D0FD72F3DC4BA6946F790776E8A5845</P>
|
|
115 |
<Q>F3DBAF51B232E334964581AE27DE17BFF90A66AE84C2BE95574082880BFF82CF</Q>
|
|
116 |
<dP>63D8A1C5B22EBD080AC861D2228DEE9E251344155ADF2C88E34F3CB096D49459</dP>
|
|
117 |
<dQ>F145A87EC23B0B059AB08690132DF07DA61F9E5C894A4D5A610B989A9694658D</dQ>
|
|
118 |
<qInv>4B8869676360EDC92F0B02F0B93580A570686E7EA3C7D39A5E572AB79314CCBD</qInv>
|
|
119 |
<ciphertext>2EAEAE1F07AAD1D3A14C2178397DFECD91C92E963511BE5CDDE8BCA79B47ECEF68F8DD2F8240DE2E05E90E2A75FAA6495CE903DE413D332CFDD2DD83BC8244C5</ciphertext>
|
|
120 |
<plaintext>123456789ABCDEF123456789ABCDEF123456789ABCDEF123456789ABCDEF</plaintext>
|
|
121 |
*/
|
|
122 |
Integer e3 = Integer(65537);
|
|
123 |
Integer p3 = Integer("FB4F79F4E8C816B816A817120901AED45D0FD72F3DC4BA6946F790776E8A5845h");
|
|
124 |
Integer q3 = Integer("F3DBAF51B232E334964581AE27DE17BFF90A66AE84C2BE95574082880BFF82CFh");
|
|
125 |
Integer cipher3 = Integer("2EAEAE1F07AAD1D3A14C2178397DFECD91C92E963511BE5CDDE8BCA79B47ECEF68F8DD2F8240DE2E05E90E2A75FAA6495CE903DE413D332CFDD2DD83BC8244C5h");
|
|
126 |
Integer ePlaintext3 = Integer("123456789ABCDEF123456789ABCDEF123456789ABCDEF123456789ABCDEFh");
|
|
127 |
|
|
128 |
CheckEPOCDecrypt(e3, p3, q3, cipher3, ePlaintext3);
|
|
129 |
}
|
|
130 |
|
|
131 |
void CheckEPOCDecrypt(Integer& e, Integer& p, Integer& q, Integer& cipher, Integer& expectedPlaintext)
|
|
132 |
{
|
|
133 |
//////////////////////////////////
|
|
134 |
// Key generation
|
|
135 |
//////////////////////////////////
|
|
136 |
|
|
137 |
// calculate n = p * q
|
|
138 |
Integer n=p*q;
|
|
139 |
|
|
140 |
Integer r1 = p;
|
|
141 |
r1-=1; // r1 = p-1
|
|
142 |
|
|
143 |
Integer r2=q;
|
|
144 |
r2-=1; // r2 = q-1
|
|
145 |
|
|
146 |
Integer r0=r1;
|
|
147 |
r0*=r2; // r0 = (p-1)(q-1)
|
|
148 |
|
|
149 |
// e * d = 1 mod ((p-1)(q-1))
|
|
150 |
// d = e^(-1) mod ((p-1)(q-1))
|
|
151 |
//! calculate multiplicative inverse of *this mod n
|
|
152 |
// Integer InverseMod(const Integer &n) const;
|
|
153 |
Integer d = e;
|
|
154 |
d = d.InverseMod(r0);
|
|
155 |
|
|
156 |
// calculate dP = d mod (p-1)
|
|
157 |
Integer dP=d;
|
|
158 |
dP%=r1;
|
|
159 |
|
|
160 |
// calculate dQ = d mod (q-1)
|
|
161 |
Integer dQ=d;
|
|
162 |
dQ%=r2;
|
|
163 |
|
|
164 |
// calculate inverse of qInv = q^(-1)mod(p)
|
|
165 |
Integer qInv=q;
|
|
166 |
qInv = qInv.InverseMod(p);
|
|
167 |
|
|
168 |
|
|
169 |
//////////////////////////////////
|
|
170 |
// Decryption
|
|
171 |
//////////////////////////////////
|
|
172 |
|
|
173 |
// m1 = c^(dP) mod(p)
|
|
174 |
Integer m1 = ModularExponentiation((cipher % p), dP, p);
|
|
175 |
|
|
176 |
// m2 = c^(dQ) mod(Q)
|
|
177 |
Integer m2 = ModularExponentiation((cipher % q), dQ, q);
|
|
178 |
|
|
179 |
// Calculate CRT
|
|
180 |
// h = (m1-m2) qInv mod(p)
|
|
181 |
Integer plainRes = m1 - m2;
|
|
182 |
plainRes *= qInv;
|
|
183 |
plainRes %= p;
|
|
184 |
|
|
185 |
// output = m2 + q * plainRes
|
|
186 |
plainRes *= q;
|
|
187 |
plainRes += m2;
|
|
188 |
|
|
189 |
// assert(expectedPlaintext==plainRes); // Not true because ciphertext includes
|
|
190 |
} // padding and plaintext doesn't. Though
|
|
191 |
// it's possible to compare the first chunk
|
|
192 |
// of plainRes with expectedPlaintext
|
|
193 |
|
|
194 |
int main(int argc, char** argv)
|
|
195 |
{
|
|
196 |
// TestRSASigning();
|
|
197 |
TestRSADecryptValues();
|
|
198 |
return 0;
|
|
199 |
}
|
|
200 |
|