#include "pch.h"
#include "eccrypto.h"
#include "ec2n.h"
#include "ecp.h"
#include "nbtheory.h"
#include "oids.h"
#include "hex.h"
NAMESPACE_BEGIN(CryptoPP)
// VC60 workaround: complains when these functions are put into an anonymous namespace
static Integer ConvertToInteger(const PolynomialMod2 &x)
{
unsigned int l = x.ByteCount();
SecByteBlock temp(l);
x.Encode(temp, l);
return Integer(temp, l);
}
static inline Integer ConvertToInteger(const Integer &x)
{
return x;
}
static bool CheckMOVCondition(const Integer &q, const Integer &r)
{
Integer t=1;
unsigned int n=q.BitCount(), m=r.BitCount();
for (unsigned int i=n; DiscreteLogWorkFactor(i)<m/2; i+=n)
{
t = (t*q)%r;
if (t == 1)
return false;
}
return true;
}
// ******************************************************************
template <class T> struct EcRecommendedParameters;
template<> struct EcRecommendedParameters<EC2N>
{
EcRecommendedParameters(const OID &oid, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h)
: oid(oid), t0(0), t1(0), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {}
EcRecommendedParameters(const OID &oid, unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h)
: oid(oid), t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {}
bool operator<(const OID &rhs) const {return oid < rhs;}
EC2N *NewEC() const
{
StringSource ssA(a, true, new HexDecoder);
StringSource ssB(b, true, new HexDecoder);
if (t0 == 0)
return new EC2N(GF2NT(t2, t3, t4), EC2N::FieldElement(ssA, ssA.MaxRetrieveable()), EC2N::FieldElement(ssB, ssB.MaxRetrieveable()));
else
return new EC2N(GF2NPP(t0, t1, t2, t3, t4), EC2N::FieldElement(ssA, ssA.MaxRetrieveable()), EC2N::FieldElement(ssB, ssB.MaxRetrieveable()));
};
OID oid;
unsigned int t0, t1, t2, t3, t4;
const char *a, *b, *g, *n;
unsigned int h;
};
template<> struct EcRecommendedParameters<ECP>
{
EcRecommendedParameters(const OID &oid, const char *p, const char *a, const char *b, const char *g, const char *n, unsigned int h)
: oid(oid), p(p), a(a), b(b), g(g), n(n), h(h) {}
inline bool operator<(const OID &rhs) const {return oid < rhs;}
ECP *NewEC() const
{
StringSource ssP(p, true, new HexDecoder);
StringSource ssA(a, true, new HexDecoder);
StringSource ssB(b, true, new HexDecoder);
return new ECP(Integer(ssP, ssP.MaxRetrieveable()), ECP::FieldElement(ssA, ssA.MaxRetrieveable()), ECP::FieldElement(ssB, ssB.MaxRetrieveable()));
};
OID oid;
const char *p;
const char *a, *b, *g, *n;
unsigned int h;
};
struct OIDLessThan
{
template <typename T>
inline bool operator()(const EcRecommendedParameters<T>& a, const OID& b) {return a.oid < b;}
template <typename T>
inline bool operator()(const OID& a, const EcRecommendedParameters<T>& b) {return a < b.oid;}
};
static void GetRecommendedParameters(const EcRecommendedParameters<EC2N> *&begin, const EcRecommendedParameters<EC2N> *&end)
{
// this array must be sorted by OID
static const EcRecommendedParameters<EC2N> rec[] = {
EcRecommendedParameters<EC2N>(ASN1::sect163k1(),
163, 7, 6, 3, 0,
"000000000000000000000000000000000000000001",
"000000000000000000000000000000000000000001",
"0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9",
"04000000000000000000020108A2E0CC0D99F8A5EF",
2),
EcRecommendedParameters<EC2N>(ASN1::sect163r1(),
163, 7, 6, 3, 0,
"07B6882CAAEFA84F9554FF8428BD88E246D2782AE2",
"0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9",
"040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883",
"03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B",
2),
EcRecommendedParameters<EC2N>(ASN1::sect239k1(),
239, 158, 0,
"000000000000000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000001",
"0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA",
"2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5",
4),
EcRecommendedParameters<EC2N>(ASN1::sect113r1(),
113, 9, 0,
"003088250CA6E7C7FE649CE85820F7",
"00E8BEE4D3E2260744188BE0E9C723",
"04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886",
"0100000000000000D9CCEC8A39E56F",
2),
EcRecommendedParameters<EC2N>(ASN1::sect113r2(),
113, 9, 0,
"00689918DBEC7E5A0DD6DFC0AA55C7",
"0095E9A9EC9B297BD4BF36E059184F",
"0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D",
"010000000000000108789B2496AF93",
2),
EcRecommendedParameters<EC2N>(ASN1::sect163r2(),
163, 7, 6, 3, 0,
"000000000000000000000000000000000000000001",
"020A601907B8C953CA1481EB10512F78744A3205FD",
"0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
"040000000000000000000292FE77E70C12A4234C33",
2),
EcRecommendedParameters<EC2N>(ASN1::sect283k1(),
283, 12, 7, 5, 0,
"000000000000000000000000000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000000000000000001",
"040503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC245849283601CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
4),
EcRecommendedParameters<EC2N>(ASN1::sect283r1(),
283, 12, 7, 5, 0,
"000000000000000000000000000000000000000000000000000000000000000000000001",
"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
"0405F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B1205303676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
2),
EcRecommendedParameters<EC2N>(ASN1::sect131r1(),
131, 8, 3, 2, 0,
"07A11B09A76B562144418FF3FF8C2570B8",
"0217C05610884B63B9C6C7291678F9D341",
"040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150",
"0400000000000000023123953A9464B54D",
2),
EcRecommendedParameters<EC2N>(ASN1::sect131r2(),
131, 8, 3, 2, 0,
"03E5A88919D7CAFCBF415F07C2176573B2",
"04B8266A46C55657AC734CE38F018F2192",
"040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F",
"0400000000000000016954A233049BA98F",
2),
EcRecommendedParameters<EC2N>(ASN1::sect193r1(),
193, 15, 0,
"0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01",
"00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814",
"0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05",
"01000000000000000000000000C7F34A778F443ACC920EBA49",
2),
EcRecommendedParameters<EC2N>(ASN1::sect193r2(),
193, 15, 0,
"0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B",
"00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE",
"0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C",
"010000000000000000000000015AAB561B005413CCD4EE99D5",
2),
EcRecommendedParameters<EC2N>(ASN1::sect233k1(),
233, 74, 0,
"000000000000000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000001",
"04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
"8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
4),
EcRecommendedParameters<EC2N>(ASN1::sect233r1(),
233, 74, 0,
"000000000000000000000000000000000000000000000000000000000001",
"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
"0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
2),
EcRecommendedParameters<EC2N>(ASN1::sect409k1(),
409, 87, 0,
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
"040060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE902374601E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
4),
EcRecommendedParameters<EC2N>(ASN1::sect409r1(),
409, 87, 0,
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
"04015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A70061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
2),
EcRecommendedParameters<EC2N>(ASN1::sect571k1(),
571, 10, 5, 2, 0,
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
"04026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C89720349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
4),
EcRecommendedParameters<EC2N>(ASN1::sect571r1(),
571, 10, 5, 2, 0,
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
"040303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
2),
};
begin = rec;
end = rec + sizeof(rec)/sizeof(rec[0]);
}
static void GetRecommendedParameters(const EcRecommendedParameters<ECP> *&begin, const EcRecommendedParameters<ECP> *&end)
{
// this array must be sorted by OID
static const EcRecommendedParameters<ECP> rec[] = {
EcRecommendedParameters<ECP>(ASN1::secp192r1(),
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
"04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
1),
EcRecommendedParameters<ECP>(ASN1::secp256r1(),
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
"046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
1),
EcRecommendedParameters<ECP>(ASN1::secp112r1(),
"DB7C2ABF62E35E668076BEAD208B",
"DB7C2ABF62E35E668076BEAD2088",
"659EF8BA043916EEDE8911702B22",
"0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500",
"DB7C2ABF62E35E7628DFAC6561C5",
1),
EcRecommendedParameters<ECP>(ASN1::secp112r2(),
"DB7C2ABF62E35E668076BEAD208B",
"6127C24C05F38A0AAAF65C0EF02C",
"51DEF1815DB5ED74FCC34C85D709",
"044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97",
"36DF0AAFD8B8D7597CA10520D04B",
4),
EcRecommendedParameters<ECP>(ASN1::secp160r1(),
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
"044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32",
"0100000000000000000001F4C8F927AED3CA752257",
1),
EcRecommendedParameters<ECP>(ASN1::secp160k1(),
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
"0000000000000000000000000000000000000000",
"0000000000000000000000000000000000000007",
"043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE",
"0100000000000000000001B8FA16DFAB9ACA16B6B3",
1),
EcRecommendedParameters<ECP>(ASN1::secp256k1(),
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000007",
"0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
1),
EcRecommendedParameters<ECP>(ASN1::secp128r1(),
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
"E87579C11079F43DD824993C2CEE5ED3",
"04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83",
"FFFFFFFE0000000075A30D1B9038A115",
1),
EcRecommendedParameters<ECP>(ASN1::secp128r2(),
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
"D6031998D1B3BBFEBF59CC9BBFF9AEE1",
"5EEEFCA380D02919DC2C6558BB6D8A5D",
"047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44",
"3FFFFFFF7FFFFFFFBE0024720613B5A3",
4),
EcRecommendedParameters<ECP>(ASN1::secp160r2(),
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
"B4E134D3FB59EB8BAB57274904664D5AF50388BA",
"0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
"0100000000000000000000351EE786A818F3A1A16B",
1),
EcRecommendedParameters<ECP>(ASN1::secp192k1(),
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
"000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000003",
"04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
"FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D",
1),
EcRecommendedParameters<ECP>(ASN1::secp224k1(),
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
"00000000000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000000000000000000000000005",
"04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
"010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",
1),
EcRecommendedParameters<ECP>(ASN1::secp224r1(),
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
"04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
1),
EcRecommendedParameters<ECP>(ASN1::secp384r1(),
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
"04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
1),
EcRecommendedParameters<ECP>(ASN1::secp521r1(),
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
"0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
1),
};
begin = rec;
end = rec + sizeof(rec)/sizeof(rec[0]);
}
template <class EC> OID ECParameters<EC>::GetNextRecommendedParametersOID(const OID &oid)
{
const EcRecommendedParameters<EC> *begin, *end;
GetRecommendedParameters(begin, end);
const EcRecommendedParameters<EC> *it = std::upper_bound(begin, end, oid, OIDLessThan());
return (it == end ? OID() : it->oid);
}
template <class EC> void ECParameters<EC>::LoadRecommendedParameters(const OID &oid)
{
const EcRecommendedParameters<EC> *begin, *end;
GetRecommendedParameters(begin, end);
const EcRecommendedParameters<EC> *it = std::lower_bound(begin, end, oid, OIDLessThan());
if (it == end || it->oid != oid)
throw UnknownOID();
const EcRecommendedParameters<EC> ¶m = *it;
m_oid = oid;
m_ec.reset(param.NewEC());
StringSource ssG(param.g, true, new HexDecoder);
bool result = m_ec->DecodePoint(m_G, ssG, ssG.MaxRetrieveable());
assert(result);
StringSource ssN(param.n, true, new HexDecoder);
m_n.Decode(ssN, ssN.MaxRetrieveable());
m_cofactorPresent = true;
m_k = param.h;
m_Gpc.SetCurveAndBase(GetCurve(), m_G);
}
template <class EC>
void ECParameters<EC>::BERDecode(BufferedTransformation &bt)
{
byte b;
if (!bt.Peek(b))
BERDecodeError();
if (b == OBJECT_IDENTIFIER)
LoadRecommendedParameters(OID(bt));
else
{
BERSequenceDecoder seq(bt);
m_ec.reset(new EC(seq));
m_G = m_ec->BERDecodePoint(seq);
m_n.BERDecode(seq);
m_cofactorPresent = !seq.EndReached();
if (m_cofactorPresent)
m_k.BERDecode(seq);
seq.MessageEnd();
m_Gpc.SetCurveAndBase(GetCurve(), m_G);
}
}
template <class EC>
void ECParameters<EC>::DEREncode(BufferedTransformation &bt) const
{
if (m_encodeAsOID && !m_oid.m_values.empty())
m_oid.DEREncode(bt);
else
{
DERSequenceEncoder seq(bt);
m_ec->DEREncode(seq);
m_ec->DEREncodePoint(seq, m_G, m_compress);
m_n.DEREncode(seq);
if (m_cofactorPresent)
m_k.DEREncode(seq);
seq.MessageEnd();
}
}
template <class EC>
bool ECParameters<EC>::ValidateParameters(RandomNumberGenerator &rng) const
{
Integer q = m_ec->FieldSize(), qSqrt = q.SquareRoot();
return m_ec->ValidateParameters(rng) && m_n!=q && m_n>4*qSqrt && VerifyPrime(rng, m_n)
&& m_ec->VerifyPoint(m_G) && !m_G.identity && m_ec->Multiply(m_n, m_G).identity
&& m_k==(q+2*qSqrt+1)/m_n && CheckMOVCondition(q, m_n);
}
template <class EC>
void ECParameters<EC>::Precompute(unsigned int precomputationStorage)
{
m_Gpc.Precompute(ExponentBitLength(), precomputationStorage);
}
template <class EC>
void ECParameters<EC>::LoadPrecomputation(BufferedTransformation &bt)
{
m_Gpc.Load(bt);
}
template <class EC>
void ECParameters<EC>::SavePrecomputation(BufferedTransformation &bt) const
{
m_Gpc.Save(bt);
}
// ******************************************************************
template <class EC>
ECPublicKey<EC>::ECPublicKey(BufferedTransformation &bt)
{
BERSequenceDecoder seq(bt);
BERSequenceDecoder algorithm(seq);
if (OID(algorithm) != ASN1::id_ecPublicKey())
BERDecodeError();
ECParameters<EC>::BERDecode(algorithm);
algorithm.MessageEnd();
SecByteBlock subjectPublicKey;
unsigned int unusedBits;
BERDecodeBitString(seq, subjectPublicKey, unusedBits);
if (!(unusedBits == 0 && m_ec->DecodePoint(m_Q, subjectPublicKey, subjectPublicKey.size)))
BERDecodeError();
seq.MessageEnd();
m_Qpc.SetCurveAndBase(GetCurve(), m_Q);
}
template <class EC>
void ECPublicKey<EC>::DEREncode(BufferedTransformation &bt) const
{
DERSequenceEncoder seq(bt);
DERSequenceEncoder algorithm(seq);
ASN1::id_ecPublicKey().DEREncode(algorithm);
ECParameters<EC>::DEREncode(algorithm);
algorithm.MessageEnd();
SecByteBlock subjectPublicKey(EncodedPointSize());
EncodePoint(subjectPublicKey, m_Q);
DEREncodeBitString(seq, subjectPublicKey.ptr, subjectPublicKey.size);
seq.MessageEnd();
}
template <class EC>
void ECPublicKey<EC>::Precompute(unsigned int precomputationStorage)
{
m_Gpc.Precompute(ExponentBitLength(), precomputationStorage);
m_Qpc.Precompute(ExponentBitLength(), precomputationStorage);
}
template <class EC>
void ECPublicKey<EC>::LoadPrecomputation(BufferedTransformation &bt)
{
m_Gpc.Load(bt);
m_Qpc.Load(bt);
}
template <class EC>
void ECPublicKey<EC>::SavePrecomputation(BufferedTransformation &bt) const
{
m_Gpc.Save(bt);
m_Qpc.Save(bt);
}
template <class EC>
Integer ECPublicKey<EC>::EncodeDigest(ECSignatureScheme ss, const byte *digest, unsigned int digestLen) const
{
if (ss == ECNR)
return NR_EncodeDigest(m_n.BitCount(), digest, digestLen);
else
{
assert(ss == ECDSA);
return DSA_EncodeDigest(m_n.BitCount(), digest, digestLen);
}
}
// ******************************************************************
template <class EC>
ECPrivateKey<EC>::ECPrivateKey(BufferedTransformation &bt)
{
BERSequenceDecoder privateKeyInfo(bt);
word32 version;
BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 1); // check version
if (version == 1)
RawDecode(privateKeyInfo, true); // for backwards compatibility
else
{
BERSequenceDecoder algorithm(privateKeyInfo);
ASN1::id_ecPublicKey().BERDecodeAndCheck(algorithm);
bool noParameters = algorithm.PeekByte() == TAG_NULL;
if (noParameters)
BERDecodeNull(algorithm);
else
ECParameters<EC>::BERDecode(algorithm);
algorithm.MessageEnd();
BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
BERSequenceDecoder privateKey(octetString);
BERDecodeUnsigned<word32>(privateKey, version, INTEGER, 1, 1); // check version
RawDecode(privateKey, noParameters);
privateKey.MessageEnd();
octetString.MessageEnd();
}
privateKeyInfo.MessageEnd();
m_Qpc.SetCurveAndBase(GetCurve(), m_Q);
}
template <class EC>
void ECPrivateKey<EC>::RawDecode(BERSequenceDecoder &seq, bool needParameters)
{
// SEC 1 ver 1.0 says privateKey (m_d) has the same length as order of the curve
// but there is some confusion so I'll allow any length
BERGeneralDecoder dec(seq, OCTET_STRING);
if (!dec.IsDefiniteLength())
BERDecodeError();
m_d.Decode(dec, dec.RemainingLength());
dec.MessageEnd();
if (needParameters && seq.PeekByte() != (CONTEXT_SPECIFIC | CONSTRUCTED | 0))
BERDecodeError();
if (!seq.EndReached() && seq.PeekByte() == (CONTEXT_SPECIFIC | CONSTRUCTED | 0))
{
BERGeneralDecoder parameters(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 0);
ECParameters<EC>::BERDecode(parameters);
parameters.MessageEnd();
}
if (seq.EndReached())
m_Q = m_Gpc.Multiply(m_d);
{
SecByteBlock subjectPublicKey;
unsigned int unusedBits;
BERGeneralDecoder publicKey(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 1);
BERDecodeBitString(publicKey, subjectPublicKey, unusedBits);
publicKey.MessageEnd();
if (!(unusedBits == 0 && m_ec->DecodePoint(m_Q, subjectPublicKey, subjectPublicKey.size)))
BERDecodeError();
}
}
template <class EC>
void ECPrivateKey<EC>::DEREncode(BufferedTransformation &bt) const
{
DERSequenceEncoder privateKeyInfo(bt);
DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version
DERSequenceEncoder algorithm(privateKeyInfo);
ASN1::id_ecPublicKey().DEREncode(algorithm);
ECParameters<EC>::DEREncode(algorithm);
algorithm.MessageEnd();
DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
DERSequenceEncoder privateKey(octetString);
DEREncodeUnsigned<word32>(privateKey, 1); // version
// SEC 1 ver 1.0 says privateKey (m_d) has the same length as order of the curve
// this will be changed to order of base point in a future version
m_d.DEREncodeAsOctetString(privateKey, m_n.ByteCount());
DERGeneralEncoder publicKey(privateKey, CONTEXT_SPECIFIC | CONSTRUCTED | 1);
SecByteBlock subjectPublicKey(EncodedPointSize());
EncodePoint(subjectPublicKey, m_Q);
DEREncodeBitString(publicKey, subjectPublicKey.ptr, subjectPublicKey.size);
publicKey.MessageEnd();
privateKey.MessageEnd();
octetString.MessageEnd();
privateKeyInfo.MessageEnd();
}
template <class EC>
void ECPrivateKey<EC>::Randomize(RandomNumberGenerator &rng)
{
m_d.Randomize(rng, 1, m_n-1, Integer::ANY);
m_Q = m_Gpc.Multiply(m_d);
m_Qpc.SetCurveAndBase(GetCurve(), m_Q);
}
// ******************************************************************
template <class EC, ECSignatureScheme SS>
bool ECDigestVerifier<EC, SS>::RawVerify(const Integer &e, const Integer &r, const Integer &s) const
{
if (SS == ECNR)
{
if (r>=m_n || r<1 || s>=m_n)
return false;
// check r == ((r*P + s*P).x + e) % m_n
Integer x = ConvertToInteger(m_Gpc.CascadeMultiply(s, m_Qpc, r).x);
return r == (x+e) % m_n;
}
else // ECDSA
{
if (r>=m_n || r<1 || s>=m_n || s<1)
return false;
Integer w = EuclideanMultiplicativeInverse(s, m_n);
Integer u1 = (e * w) % m_n;
Integer u2 = (r * w) % m_n;
// check r == (u1*P + u2*P).x % n
return r == ConvertToInteger(m_Gpc.CascadeMultiply(u1, m_Qpc, u2).x) % m_n;
}
}
template <class EC, ECSignatureScheme SS>
bool ECDigestVerifier<EC, SS>::VerifyDigest(const byte *digest, unsigned int digestLen, const byte *signature) const
{
assert (digestLen <= MaxDigestLength());
Integer e = EncodeDigest(SS, digest, digestLen);
Integer r(signature, ExponentLength());
Integer s(signature+ExponentLength(), ExponentLength());
return RawVerify(e, r, s);
}
// ******************************************************************
template <class EC, ECSignatureScheme SS>
void ECDigestSigner<EC, SS>::RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const
{
if (SS == ECNR)
{
do
{
// convert kP.x into an Integer
Integer x = ConvertToInteger(m_Gpc.Multiply(k).x);
r = (x+e) % m_n;
s = (k-m_d*r) % m_n;
} while (!r);
}
else
{
do
{
r = ConvertToInteger(m_Gpc.Multiply(k).x) % m_n;
Integer kInv = EuclideanMultiplicativeInverse(k, m_n);
s = (kInv * (m_d*r + e)) % m_n;
} while (!r || !s);
}
}
template <class EC, ECSignatureScheme SS>
void ECDigestSigner<EC, SS>::SignDigest(RandomNumberGenerator &rng, const byte *digest, unsigned int digestLen, byte *signature) const
{
Integer r, s;
Integer e = EncodeDigest(SS, digest, digestLen);
Integer k(rng, 1, m_n-1, Integer::ANY);
RawSign(k, e, r, s);
r.Encode(signature, ExponentLength());
s.Encode(signature+ExponentLength(), ExponentLength());
}
// ******************************************************************
template <class EC>
void ECDHC<EC>::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
{
Integer x(rng, 1, m_n-1);
Point Q = m_Gpc.Multiply(x);
x.Encode(privateKey, PrivateKeyLength());
EncodePoint(publicKey, Q);
}
template <class EC>
bool ECDHC<EC>::Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey) const
{
Point W;
if (!GetCurve().DecodePoint(W, otherPublicKey, PublicKeyLength()))
return false;
if (validateOtherPublicKey && !GetCurve().VerifyPoint(W))
return false;
Integer s(privateKey, PrivateKeyLength());
Point Q = GetCurve().Multiply(m_k*s, W);
if (Q.identity)
return false;
Q.x.Encode(agreedValue, AgreedValueLength());
return true;
}
// ******************************************************************
template <class EC>
void ECMQVC<EC>::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
{
Integer x(rng, 1, m_n-1);
Point Q = m_Gpc.Multiply(x);
x.Encode(privateKey, StaticPrivateKeyLength());
EncodePoint(publicKey, Q);
}
template <class EC>
void ECMQVC<EC>::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
{
Integer x(rng, 1, m_n-1);
Point Q = m_Gpc.Multiply(x);
x.Encode(privateKey, ExponentLength());
EncodePoint(privateKey+ExponentLength(), Q);
EncodePoint(publicKey, Q);
}
template <class EC>
bool ECMQVC<EC>::Agree(byte *agreedValue, const byte *staticPrivateKey, const byte *ephemeralPrivateKey, const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, bool validateStaticOtherPublicKey) const
{
Point WW, VV;
if (!(GetCurve().DecodePoint(WW, staticOtherPublicKey, StaticPublicKeyLength())
&& GetCurve().DecodePoint(VV, ephemeralOtherPublicKey, EphemeralPublicKeyLength())))
return false;
if (!GetCurve().VerifyPoint(VV) || (validateStaticOtherPublicKey && !GetCurve().VerifyPoint(WW)))
return false;
Integer s(staticPrivateKey, StaticPrivateKeyLength());
Integer u(ephemeralPrivateKey, ExponentLength());
Point V;
if (!GetCurve().DecodePoint(V, ephemeralPrivateKey+ExponentLength(), EncodedPointSize()))
return false;
Integer h2 = Integer::Power2((m_n.BitCount()+1)/2);
Integer e = ((h2+ConvertToInteger(V.x)%h2)*s+u) % m_n;
Point Q = GetCurve().CascadeMultiply(m_k*e, VV, m_k*(e*(h2+ConvertToInteger(VV.x)%h2)%m_n), WW);
if (Q.identity)
return false;
Q.x.Encode(agreedValue, AgreedValueLength());
return true;
}
template class ECParameters<EC2N>;
template class ECParameters<ECP>;
template class ECPublicKey<EC2N>;
template class ECPublicKey<ECP>;
template class ECPrivateKey<EC2N>;
template class ECPrivateKey<ECP>;
template class ECDigestVerifier<EC2N, ECDSA>;
template class ECDigestVerifier<ECP, ECDSA>;
template class ECDigestSigner<EC2N, ECDSA>;
template class ECDigestSigner<ECP, ECDSA>;
template class ECDigestVerifier<EC2N, ECNR>;
template class ECDigestVerifier<ECP, ECNR>;
template class ECDigestSigner<EC2N, ECNR>;
template class ECDigestSigner<ECP, ECNR>;
template class ECDHC<EC2N>;
template class ECDHC<ECP>;
template class ECMQVC<EC2N>;
template class ECMQVC<ECP>;
NAMESPACE_END