source: git/src-cryptopp/rsa.cpp

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 9.1 KB
Line 
1// rsa.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4#include "rsa.h"
5#include "asn.h"
6#include "sha.h"
7#include "oids.h"
8#include "modarith.h"
9#include "nbtheory.h"
10#include "algparam.h"
11#include "fips140.h"
12
13#if CRYPTOPP_DEBUG && !defined(CRYPTOPP_DOXYGEN_PROCESSING) && !defined(CRYPTOPP_IS_DLL)
14#include "pssr.h"
15NAMESPACE_BEGIN(CryptoPP)
16void RSA_TestInstantiations()
17{
18        RSASS<PKCS1v15, SHA>::Verifier x1(1, 1);
19        RSASS<PKCS1v15, SHA>::Signer x2(NullRNG(), 1);
20        RSASS<PKCS1v15, SHA>::Verifier x3(x2);
21        RSASS<PKCS1v15, SHA>::Verifier x4(x2.GetKey());
22        RSASS<PSS, SHA>::Verifier x5(x3);
23#ifndef __MWERKS__
24        RSASS<PSSR, SHA>::Signer x6 = x2;
25        x3 = x2;
26        x6 = x2;
27#endif
28        RSAES<PKCS1v15>::Encryptor x7(x2);
29#ifndef __GNUC__
30        RSAES<PKCS1v15>::Encryptor x8(x3);
31#endif
32        RSAES<OAEP<SHA> >::Encryptor x9(x2);
33
34        x4 = x2.GetKey();
35}
36NAMESPACE_END
37#endif
38
39#ifndef CRYPTOPP_IMPORTS
40
41NAMESPACE_BEGIN(CryptoPP)
42
43OID RSAFunction::GetAlgorithmID() const
44{
45        return ASN1::rsaEncryption();
46}
47
48void RSAFunction::BERDecodePublicKey(BufferedTransformation &bt, bool, size_t)
49{
50        BERSequenceDecoder seq(bt);
51                m_n.BERDecode(seq);
52                m_e.BERDecode(seq);
53        seq.MessageEnd();
54}
55
56void RSAFunction::DEREncodePublicKey(BufferedTransformation &bt) const
57{
58        DERSequenceEncoder seq(bt);
59                m_n.DEREncode(seq);
60                m_e.DEREncode(seq);
61        seq.MessageEnd();
62}
63
64Integer RSAFunction::ApplyFunction(const Integer &x) const
65{
66        DoQuickSanityCheck();
67        return a_exp_b_mod_c(x, m_e, m_n);
68}
69
70bool RSAFunction::Validate(RandomNumberGenerator& rng, unsigned int level) const
71{
72        CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(level);
73
74        bool pass = true;
75        pass = pass && m_n > Integer::One() && m_n.IsOdd();
76        pass = pass && m_e > Integer::One() && m_e.IsOdd() && m_e < m_n;
77        return pass;
78}
79
80bool RSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
81{
82        return GetValueHelper(this, name, valueType, pValue).Assignable()
83                CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
84                CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent)
85                ;
86}
87
88void RSAFunction::AssignFrom(const NameValuePairs &source)
89{
90        AssignFromHelper(this, source)
91                CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
92                CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
93                ;
94}
95
96// *****************************************************************************
97
98class RSAPrimeSelector : public PrimeSelector
99{
100public:
101        RSAPrimeSelector(const Integer &e) : m_e(e) {}
102        bool IsAcceptable(const Integer &candidate) const {return RelativelyPrime(m_e, candidate-Integer::One());}
103        Integer m_e;
104};
105
106void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
107{
108        int modulusSize = 2048;
109        alg.GetIntValue(Name::ModulusSize(), modulusSize) || alg.GetIntValue(Name::KeySize(), modulusSize);
110
111        CRYPTOPP_ASSERT(modulusSize >= 16);
112        if (modulusSize < 16)
113                throw InvalidArgument("InvertibleRSAFunction: specified modulus size is too small");
114
115        m_e = alg.GetValueWithDefault(Name::PublicExponent(), Integer(17));
116
117        CRYPTOPP_ASSERT(m_e >= 3); CRYPTOPP_ASSERT(!m_e.IsEven());
118        if (m_e < 3 || m_e.IsEven())
119                throw InvalidArgument("InvertibleRSAFunction: invalid public exponent");
120
121        RSAPrimeSelector selector(m_e);
122        AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize)
123                (Name::PointerToPrimeSelector(), selector.GetSelectorPointer());
124        m_p.GenerateRandom(rng, primeParam);
125        m_q.GenerateRandom(rng, primeParam);
126
127        m_d = m_e.InverseMod(LCM(m_p-1, m_q-1));
128        CRYPTOPP_ASSERT(m_d.IsPositive());
129
130        m_dp = m_d % (m_p-1);
131        m_dq = m_d % (m_q-1);
132        m_n = m_p * m_q;
133        m_u = m_q.InverseMod(m_p);
134
135        if (FIPS_140_2_ComplianceEnabled())
136        {
137                RSASS<PKCS1v15, SHA>::Signer signer(*this);
138                RSASS<PKCS1v15, SHA>::Verifier verifier(signer);
139                SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier);
140
141                RSAES<OAEP<SHA> >::Decryptor decryptor(*this);
142                RSAES<OAEP<SHA> >::Encryptor encryptor(decryptor);
143                EncryptionPairwiseConsistencyTest_FIPS_140_Only(encryptor, decryptor);
144        }
145}
146
147void InvertibleRSAFunction::Initialize(RandomNumberGenerator &rng, unsigned int keybits, const Integer &e)
148{
149        GenerateRandom(rng, MakeParameters(Name::ModulusSize(), (int)keybits)(Name::PublicExponent(), e+e.IsEven()));
150}
151
152void InvertibleRSAFunction::Initialize(const Integer &n, const Integer &e, const Integer &d)
153{
154        if (n.IsEven() || e.IsEven() | d.IsEven())
155                throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key");
156
157        m_n = n;
158        m_e = e;
159        m_d = d;
160
161        Integer r = --(d*e);
162        unsigned int s = 0;
163        while (r.IsEven())
164        {
165                r >>= 1;
166                s++;
167        }
168
169        ModularArithmetic modn(n);
170        for (Integer i = 2; ; ++i)
171        {
172                Integer a = modn.Exponentiate(i, r);
173                if (a == 1)
174                        continue;
175                Integer b;
176                unsigned int j = 0;
177                while (a != n-1)
178                {
179                        b = modn.Square(a);
180                        if (b == 1)
181                        {
182                                m_p = GCD(a-1, n);
183                                m_q = n/m_p;
184                                m_dp = m_d % (m_p-1);
185                                m_dq = m_d % (m_q-1);
186                                m_u = m_q.InverseMod(m_p);
187                                return;
188                        }
189                        if (++j == s)
190                                throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key");
191                        a = b;
192                }
193        }
194}
195
196void InvertibleRSAFunction::BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t)
197{
198        BERSequenceDecoder privateKey(bt);
199                word32 version;
200                BERDecodeUnsigned<word32>(privateKey, version, INTEGER, 0, 0);  // check version
201                m_n.BERDecode(privateKey);
202                m_e.BERDecode(privateKey);
203                m_d.BERDecode(privateKey);
204                m_p.BERDecode(privateKey);
205                m_q.BERDecode(privateKey);
206                m_dp.BERDecode(privateKey);
207                m_dq.BERDecode(privateKey);
208                m_u.BERDecode(privateKey);
209        privateKey.MessageEnd();
210}
211
212void InvertibleRSAFunction::DEREncodePrivateKey(BufferedTransformation &bt) const
213{
214        DERSequenceEncoder privateKey(bt);
215                DEREncodeUnsigned<word32>(privateKey, 0);       // version
216                m_n.DEREncode(privateKey);
217                m_e.DEREncode(privateKey);
218                m_d.DEREncode(privateKey);
219                m_p.DEREncode(privateKey);
220                m_q.DEREncode(privateKey);
221                m_dp.DEREncode(privateKey);
222                m_dq.DEREncode(privateKey);
223                m_u.DEREncode(privateKey);
224        privateKey.MessageEnd();
225}
226
227Integer InvertibleRSAFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const
228{
229        DoQuickSanityCheck();
230        ModularArithmetic modn(m_n);
231        Integer r, rInv;
232        do {    // do this in a loop for people using small numbers for testing
233                r.Randomize(rng, Integer::One(), m_n - Integer::One());
234                rInv = modn.MultiplicativeInverse(r);
235        } while (rInv.IsZero());
236        Integer re = modn.Exponentiate(r, m_e);
237        re = modn.Multiply(re, x);                      // blind
238        // here we follow the notation of PKCS #1 and let u=q inverse mod p
239        // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q
240        Integer y = ModularRoot(re, m_dq, m_dp, m_q, m_p, m_u);
241        y = modn.Multiply(y, rInv);                             // unblind
242        if (modn.Exponentiate(y, m_e) != x)             // check
243                throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: computational error during private key operation");
244        return y;
245}
246
247bool InvertibleRSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
248{
249        bool pass = RSAFunction::Validate(rng, level);
250        pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
251        pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
252        pass = pass && m_d > Integer::One() && m_d.IsOdd() && m_d < m_n;
253        pass = pass && m_dp > Integer::One() && m_dp.IsOdd() && m_dp < m_p;
254        pass = pass && m_dq > Integer::One() && m_dq.IsOdd() && m_dq < m_q;
255        pass = pass && m_u.IsPositive() && m_u < m_p;
256        if (level >= 1)
257        {
258                pass = pass && m_p * m_q == m_n;
259                pass = pass && m_e*m_d % LCM(m_p-1, m_q-1) == 1;
260                pass = pass && m_dp == m_d%(m_p-1) && m_dq == m_d%(m_q-1);
261                pass = pass && m_u * m_q % m_p == 1;
262        }
263        if (level >= 2)
264                pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
265        return pass;
266}
267
268bool InvertibleRSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
269{
270        return GetValueHelper<RSAFunction>(this, name, valueType, pValue).Assignable()
271                CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
272                CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
273                CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent)
274                CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime1PrivateExponent)
275                CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime2PrivateExponent)
276                CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
277                ;
278}
279
280void InvertibleRSAFunction::AssignFrom(const NameValuePairs &source)
281{
282        AssignFromHelper<RSAFunction>(this, source)
283                CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
284                CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
285                CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent)
286                CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime1PrivateExponent)
287                CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime2PrivateExponent)
288                CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
289                ;
290}
291
292// *****************************************************************************
293
294Integer RSAFunction_ISO::ApplyFunction(const Integer &x) const
295{
296        Integer t = RSAFunction::ApplyFunction(x);
297        return t % 16 == 12 ? t : m_n - t;
298}
299
300Integer InvertibleRSAFunction_ISO::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const
301{
302        Integer t = InvertibleRSAFunction::CalculateInverse(rng, x);
303        return STDMIN(t, m_n-t);
304}
305
306NAMESPACE_END
307
308#endif
Note: See TracBrowser for help on using the repository browser.