From c8aaa5aae313f8dd9af264fa7561fa5d5b989e94 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Sun, 10 Jan 2016 23:31:18 +0100 Subject: [PATCH 01/21] Added Montgomery support This check-in enables support for elliptic curves over prime fields using the Montgomery equation. Support for Edwards curves will follow as soon as all bugs are eliminated. --- eccrypto.cpp | 70 +++++++++ eccrypto.h | 6 + ecpm.cpp | 396 +++++++++++++++++++++++++++++++++++++++++++++++++++ ecpm.h | 142 ++++++++++++++++++ oids.h | 26 ++++ test.cpp | 1 + validat1.cpp | 1 + validat2.cpp | 107 ++++++++++++++ validate.h | 1 + 9 files changed, 750 insertions(+) create mode 100644 ecpm.cpp create mode 100644 ecpm.h diff --git a/eccrypto.cpp b/eccrypto.cpp index 3ac4f194..3e39d92f 100644 --- a/eccrypto.cpp +++ b/eccrypto.cpp @@ -122,6 +122,24 @@ template<> struct EcRecommendedParameters unsigned int h; }; +template<> struct EcRecommendedParameters +{ + 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) {} + ECPM *NewEC() const + { + StringSource ssP(p, true, new HexDecoder); + StringSource ssA(A, true, new HexDecoder); + StringSource ssB(B, true, new HexDecoder); + return new ECPM(Integer(ssP, (size_t)ssP.MaxRetrievable()), ECPM::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), ECPM::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); + }; + + OID oid; + const char *p; + const char *A, *B, *g, *n; + unsigned int h; +}; + struct OIDLessThan { template @@ -430,6 +448,58 @@ static void GetRecommendedParameters(const EcRecommendedParameters *&begin, end = rec + sizeof(rec)/sizeof(rec[0]); } +static void GetRecommendedParameters(const EcRecommendedParameters *&begin, const EcRecommendedParameters *&end) +{ + // this array must be sorted by OID + static const EcRecommendedParameters rec[] = + { + EcRecommendedParameters(ASN1::cryptoppM221(), + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD", + "0000000000000000000000000000000000000000000000000001C93A", + "00000000000000000000000000000000000000000000000000000001", + "04000000000000000000000000000000000000000000000000000000040F7ACDD2A4939571D1CEF14ECA37C228E61DBFF10707DC6C08C5056D", + "040000000000000000000000000015A08ED730E8A2F77F005042605B", + 8), + EcRecommendedParameters(ASN1::cryptoppM383(), + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45", + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F82FE", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C1EC7ED04AAF834AF310E304B2DA0F328E7C165F0E8988ABD3992861290F617AA1F1B2E7D0B6E332E969991B62555E77E", + "10000000000000000000000000000000000000000000000006C79673AC36BA6E7A32576F7B1B249E46BBC225BE9071D7", + 8), + EcRecommendedParameters(ASN1::cryptoppM511(), + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081806", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052fbdc0ad8530803d28fdbad354bb488d32399ac1cf8f6e01ee3f96389b90c809422b9429e8a43dbf49308ac4455940abe9f1dbca542093a895e30a64af056fa5", + "100000000000000000000000000000000000000000000000000000000000000017B5FEFF30C7F5677AB2AEEBD13779A2AC125042A6AA10BFA54C15BAB76BAF1B", + 8), + EcRecommendedParameters(ASN1::cryptoppCurve383187(), + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038251", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051EEBE07DC1871896732B12D5504A32370471965C7A11F2C89865F855AB3CBD7C224E3620C31AF3370788457DD5CE46DF", + "1000000000000000000000000000000000000000000000000e85a85287a1488acd41ae84b2b7030446f72088b00a0e21", + 8), + EcRecommendedParameters(ASN1::ietfCurve25519(), + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED", + "0000000000000000000000000000000000000000000000000000000000076D06", + "0000000000000000000000000000000000000000000000000000000000000001", + "04000000000000000000000000000000000000000000000000000000000000000920AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9", + "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", + 8), + EcRecommendedParameters(ASN1::ietfCurve448(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000262A6", + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057D235D1295F5B1F66C98AB6E58326FCECBAE5D34F55545D060F75DC28DF3F6EDB8027E2346430D211312C4B150677AF76FD7223D457B5B1A", + "3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3", + 4), + }; + begin = rec; + end = rec + sizeof(rec) / sizeof(rec[0]); +} + template OID DL_GroupParameters_EC::GetNextRecommendedParametersOID(const OID &oid) { const EcRecommendedParameters *begin, *end; diff --git a/eccrypto.h b/eccrypto.h index a3d15e95..3adbbf9c 100644 --- a/eccrypto.h +++ b/eccrypto.h @@ -319,18 +319,24 @@ NAMESPACE_BEGIN(CryptoPP) CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; NAMESPACE_END diff --git a/ecpm.cpp b/ecpm.cpp new file mode 100644 index 00000000..163308de --- /dev/null +++ b/ecpm.cpp @@ -0,0 +1,396 @@ +// ecpm.cpp - written and placed in public domain by Jean-Pierre Muench. Copyright assigned to the Crypto++ project. + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "ecp.h" +#include "ecpm.h" +#include "asn.h" +#include "integer.h" +#include "nbtheory.h" +#include "modarith.h" +#include "filters.h" +#include "algebra.cpp" + +NAMESPACE_BEGIN(CryptoPP) + +ANONYMOUS_NAMESPACE_BEGIN +static inline ECP::Point ToMontgomery(const ModularArithmetic &mr, const ECP::Point &P) // straight from ecp.cpp +{ + return P.identity ? P : ECP::Point(mr.ConvertIn(P.x), mr.ConvertIn(P.y)); +} + +static inline ECP::Point FromMontgomery(const ModularArithmetic &mr, const ECP::Point &P) // straight from ecp.cpp +{ + return P.identity ? P : ECP::Point(mr.ConvertOut(P.x), mr.ConvertOut(P.y)); +} +static inline ECP* GenerateWeierstrassCurve(const ECPM& MontgomeryCurve) +{ + const Integer& A = MontgomeryCurve.GetA(); + const Integer& B = MontgomeryCurve.GetB(); + const ModularArithmetic& Field = MontgomeryCurve.GetField(); + + // now construct the equivalent Weierstrass curve + // refer to https://crypto.stackexchange.com/q/27842 for the details + // use m_FieldPtr to ensure encoding (eventual Montgomery Representation) is handled correctly + //the transformations also appear independently on http ://safecurves.cr.yp.to/equation.html + + // a = (3-A)/(3B^2) + Integer aWeierstrass = Field.Subtract(3, Field.Square(A)); // a = 3 - A + aWeierstrass = Field.Divide(aWeierstrass, Field.Multiply(3, Field.Square(B))); // a = a / (3B^2) + // b = (2A^3-9A) / (27 B^3) + Integer bWeierstrass = Field.Multiply(A, Field.Subtract(Field.Multiply(2, Field.Square(A)), 9)); // b = A(2A^2-9) + bWeierstrass = Field.Divide(bWeierstrass, Field.Multiply(27, Field.Exponentiate(B, 3))); // b = b / (27 B^3) + + return new ECP(MontgomeryCurve.GetField().GetModulus(), aWeierstrass, bWeierstrass); +} +NAMESPACE_END + +ECPM::ECPM(const Integer &modulus, const FieldElement &A, const FieldElement &B): + m_fieldPtr(new Field(modulus)) +{ + // store A and B for later use + m_A = A.IsNegative() ? (A + modulus) : A;// straight from ecp.cpp + m_B = B.IsNegative() ? (B + modulus) : B;// straight from ecp.cpp + + m_ComputeEngine.reset(GenerateWeierstrassCurve(*this)); + + // to speed up the conversions + m_AThirds = m_fieldPtr->Divide(m_A, 3); + m_BInv = m_fieldPtr->MultiplicativeInverse(m_B); +} + +// straight adaption from ecp.cpp +ECPM::ECPM(const ECPM &ecpm, bool convertToMontgomeryRepresentation) +{ + if (convertToMontgomeryRepresentation && !ecpm.GetField().IsMontgomeryRepresentation()) + { + m_fieldPtr.reset(new MontgomeryRepresentation(ecpm.GetField().GetModulus())); + m_ComputeEngine.reset(new ECP(*ecpm.m_ComputeEngine.get(),convertToMontgomeryRepresentation)); + m_A = GetField().ConvertIn(ecpm.m_A); + m_B = GetField().ConvertIn(ecpm.m_B); + m_AThirds = GetField().ConvertIn(ecpm.m_AThirds); + m_BInv = GetField().ConvertIn(ecpm.m_BInv); + } + else + operator=(ecpm); +} + +ECPM::ECPM(BufferedTransformation &bt) + : m_fieldPtr(new Field(bt)) +{ + BERSequenceDecoder seq(bt); + GetField().BERDecodeElement(seq, m_A); + GetField().BERDecodeElement(seq, m_B); + // skip optional seed + if (!seq.EndReached()) + { + SecByteBlock seed; + unsigned int unused; + BERDecodeBitString(seq, seed, unused); + } + seq.MessageEnd(); + + m_ComputeEngine.reset(GenerateWeierstrassCurve(*this)); + + m_AThirds = m_fieldPtr->Divide(m_A, 3); + m_BInv = m_fieldPtr->MultiplicativeInverse(m_B); +} + +// straight adaption from ecp.cpp +void ECPM::DEREncode(BufferedTransformation &bt) const +{ + GetField().DEREncode(bt); + DERSequenceEncoder seq(bt); + GetField().DEREncodeElement(seq, m_A); + GetField().DEREncodeElement(seq, m_B); + seq.MessageEnd(); +} + +// straight adaption from ecp.cpp +bool ECPM::DecodePoint(ECPM::Point &P, const byte *encodedPoint, size_t encodedPointLen) const +{ + StringStore store(encodedPoint, encodedPointLen); + return DecodePoint(P, store, encodedPointLen); +} + +// straight adaption from ecp.cpp +bool ECPM::DecodePoint(ECPM::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const +{ + byte type; + if (encodedPointLen < 1 || !bt.Get(type)) + return false; + + switch (type) + { + case 0: + P.identity = true; + return true; + case 2: + case 3: + { + if (encodedPointLen != EncodedPointSize(true)) + return false; + + Integer p = FieldSize(); + + P.identity = false; + P.x.Decode(bt, GetField().MaxElementByteLength()); + // curve is: By^2=x^3+Ax^2+x <=> y=sqrt(x/B(x(A+x)+1) + P.y = (m_BInv * P.x *(P.x * (P.x + m_A) + Integer::One()))%p; + + if (Jacobi(P.y, p) != 1) + return false; + + P.y = ModularSquareRoot(P.y, p); + + if ((type & 1) != P.y.GetBit(0)) + P.y = p - P.y; + + return true; + } + case 4: + { + if (encodedPointLen != EncodedPointSize(false)) + return false; + + unsigned int len = GetField().MaxElementByteLength(); + P.identity = false; + P.x.Decode(bt, len); + P.y.Decode(bt, len); + return true; + } + default: + return false; + } +} + +// straight adaption from ecp.cpp +void ECPM::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + if (P.identity) + NullStore().TransferTo(bt, EncodedPointSize(compressed)); + else if (compressed) + { + bt.Put(2 + P.y.GetBit(0)); + P.x.Encode(bt, GetField().MaxElementByteLength()); + } + else + { + unsigned int len = GetField().MaxElementByteLength(); + bt.Put(4); // uncompressed + P.x.Encode(bt, len); + P.y.Encode(bt, len); + } +} + +// straight adaption from ecp.cpp +void ECPM::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const +{ + ArraySink sink(encodedPoint, EncodedPointSize(compressed)); + EncodePoint(sink, P, compressed); + assert(sink.TotalPutLength() == EncodedPointSize(compressed)); +} + +// straight adaption from ecp.cpp +ECPM::Point ECPM::BERDecodePoint(BufferedTransformation &bt) const +{ + SecByteBlock str; + BERDecodeOctetString(bt, str); + Point P; + if (!DecodePoint(P, str, str.size())) + BERDecodeError(); + return P; +} + +// straight adaption from ecp.cpp +void ECPM::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + SecByteBlock str(EncodedPointSize(compressed)); + EncodePoint(str, P, compressed); + DEREncodeOctetString(bt, str); +} + +// straight adaption from ecp.cpp +bool ECPM::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const +{ + Integer p = FieldSize(); + + bool pass = p.IsOdd(); + pass = pass && !m_A.IsNegative() && m_A

= 1) + pass = pass && ((m_B * (m_A * m_A - 4)) % p).IsPositive(); + + if (level >= 2) + pass = pass && VerifyPrime(rng, p); + + return pass; +} + +// straight adaption from ecp.cpp +bool ECPM::VerifyPoint(const Point &P) const +{ + const FieldElement &x = P.x, &y = P.y; + Integer p = FieldSize(); + + // use the field arithmetic here, in case our data is in Montgomery form + // ecp.cpp does this with plain integer arithmetic -> will fail if montgomery representation is on, but was never called when montgomery representation was on + const FieldElement IsOnCurve = m_fieldPtr->Subtract(m_fieldPtr->Multiply(x,(m_fieldPtr->Add(1,m_fieldPtr->Multiply(x,(m_fieldPtr->Add(m_A,x)))))),m_fieldPtr->Multiply(m_B,m_fieldPtr->Square(y))); + + return P.identity || + (!x.IsNegative() && x

0 == x(1+x(A+x))-By^2 +} + +// straight adaption from ecp.cpp +bool ECPM::Equal(const Point &P, const Point &Q) const +{ + if (P.identity && Q.identity) + return true; + + if (P.identity && !Q.identity) + return false; + + if (!P.identity && Q.identity) + return false; + + return (GetField().Equal(P.x, Q.x) && GetField().Equal(P.y, Q.y)); +} + +// straight adaption from ecp.cpp +const ECPM::Point& ECPM::Identity() const +{ + return Singleton().Ref(); +} + +// straight adaption from ecp.cpp +const ECPM::Point& ECPM::Inverse(const Point &P) const +{ + if (P.identity) + return P; + else + { + m_R.identity = false; + m_R.x = P.x; + m_R.y = GetField().Inverse(P.y); + return m_R; + } +} + +// straight adaption from ecp.cpp +const ECPM::Point& ECPM::Add(const Point &P, const Point &Q) const +{ + if (P.identity) return Q; + if (Q.identity) return P; + if (GetField().Equal(P.x, Q.x)) + return GetField().Equal(P.y, Q.y) ? Double(P) : Identity(); + + FieldElement t = GetField().Subtract(Q.y, P.y); // t = y_Q - y_P + t = GetField().Divide(t, GetField().Subtract(Q.x, P.x)); // t = (y_Q - y_P) / (x_Q - x_P) + FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Subtract(GetField().Multiply(m_B,GetField().Square(t)), P.x), Q.x),m_A); // x = B*t^2-x_P-x_Q-A + m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); // y = t * (x_P - x) - y_P + + m_R.x.swap(x); + m_R.identity = false; + return m_R; +} + +// straight adaption from ecp.cpp +const ECPM::Point& ECPM::Double(const Point &P) const +{ + if (P.identity || P.y == GetField().Identity()) return Identity(); + + FieldElement t = GetField().Add(GetField().Double(P.x), P.x);// t = 2x_P + x_P = 3x_P + t = GetField().Add(GetField().Multiply(P.x,GetField().Add(t,GetField().Double(m_A))), GetField().ConvertIn(1)); // x_P * ( t + 2 * A)+1 + FieldElement h1= GetField().Multiply(t, m_BInv), h2= GetField().Double(P.y); // put this in two steps or it fails somehow otherwise + t = GetField().Divide(h1, h2); // t = (x_P(3x_P + 2A)+1)/(2B*y_P) + FieldElement& x = m_R.x; + x = GetField().Multiply(m_B, GetField().Square(t)); // put this in two steps or it fails somehow otherwise + x = GetField().Subtract(GetField().Subtract(x, GetField().Double(P.x)), m_A); // x = B * t^2 - A - x_1 - x_2 + m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); // t (x_P - x) -y_P + + m_R.identity = false; + return m_R; +} + +// straight adaption from ecp.cpp +ECPM::Point ECPM::ScalarMultiply(const Point &P, const Integer &k) const +{ + Element result; + if (k.BitCount() <= 5) + AbstractGroup::SimultaneousMultiply(&result, P, &k, 1); + else + ECPM::SimultaneousMultiply(&result, P, &k, 1); + + return result; +} + +// this is probably the cause of the issue +void ECPM::SimultaneousMultiply(ECPM::Point *results, const ECPM::Point &P, const Integer *expBegin, unsigned int expCount) const +{ + Point ConvertedBase = MontgomeryToWeierstrass(P); + // let the compute engine do its optimized work + m_ComputeEngine->SimultaneousMultiply(results, ConvertedBase, expBegin, expCount); + + // fetch the results and convert them back to our preferred form + for (unsigned int i = 0; i < expCount; ++i) + results[i] = WeierstrassToMontgomery(results[i]); + + return; + + // implement Montgomery ladder below +} + +// straight adaption from ecp.cpp +ECPM::Point ECPM::CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const +{ + if (!GetField().IsMontgomeryRepresentation()) + { + ECPM ecpmr(*this, true); + const ModularArithmetic &mr = ecpmr.GetField(); + return FromMontgomery(mr, ecpmr.CascadeScalarMultiply(ToMontgomery(mr, P), k1, ToMontgomery(mr, Q), k2)); + } + else + return AbstractGroup::CascadeScalarMultiply(P, k1, Q, k2); +} + +// added as ECP doesn't offer a Clone() function which is required for assignment +void ECPM::operator=(const ECPM& rhs) +{ + m_A = rhs.m_A; + m_AThirds = rhs.m_AThirds; + m_B = rhs.m_B; + m_BInv = rhs.m_BInv; + m_fieldPtr = rhs.m_fieldPtr->Clone(); + m_ComputeEngine.reset(new ECP(*rhs.m_ComputeEngine,rhs.m_ComputeEngine->GetField().IsMontgomeryRepresentation())); +} + +// converts weierstrass points to montgomery points +// it can be checked at https://crypto.stackexchange.com/q/27842 and http://safecurves.cr.yp.to/equation.html +inline ECPM::Point ECPM::WeierstrassToMontgomery(const Point& In) const +{ + // (x,y) -> (Bx-A/3,By) + ECPPoint Out; + Out.identity = In.identity; + Out.x = GetField().Subtract(m_fieldPtr->Multiply(m_B,In.x),m_AThirds); + Out.y = GetField().Multiply(In.y,m_B); + return Out; +} + +// converts weierstrass points to montgomery points, the math *should* be right +inline ECPM::Point ECPM::MontgomeryToWeierstrass(const Point& In) const +{ + // (x,y) -> ((x+A/3)/B,y/B) + ECPPoint Out; + Out.identity = In.identity; + Out.x = GetField().Multiply(m_fieldPtr->Add(In.x,m_AThirds),m_BInv); + Out.y = GetField().Multiply(In.y, m_BInv); + return Out; +} + +NAMESPACE_END + +#endif diff --git a/ecpm.h b/ecpm.h new file mode 100644 index 00000000..f23a9dda --- /dev/null +++ b/ecpm.h @@ -0,0 +1,142 @@ +// ecpm.h - written and placed in public domain by Jean-Pierre Muench. Copyright assigned to Crypto++ project. + +//! \file ecpm.h +//! \brief Classes for montgomery curves over prime fields + +#ifndef CRYPTOPP_ECPM_H +#define CRYPTOPP_ECPM_H + +#include "cryptlib.h" +#include "integer.h" +#include "modarith.h" +#include "eprecomp.h" +#include "smartptr.h" +#include "pubkey.h" +#include "ecp.h" + +NAMESPACE_BEGIN(CryptoPP) + +// strategy: +// first do it the conservative way: each SimultaneousMultiply is followed and preceeded by a transformation +// later replace this algorithm using an optimized algorithm using the Montgomery Ladder +class CRYPTOPP_DLL ECPM : public AbstractGroup +{ +public: + typedef ModularArithmetic Field; + typedef Integer FieldElement; + typedef ECPPoint Point; + + ECPM() {} + ECPM(const ECPM &ecp, bool convertToMontgomeryRepresentation = false); + ECPM(const Integer &modulus, const FieldElement &A, const FieldElement &B); + // construct from BER encoded parameters + // this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters + ECPM(BufferedTransformation &bt); + + // encode the fields fieldID and curve of the sequence ECParameters + void DEREncode(BufferedTransformation &bt) const; + + bool Equal(const Point &P, const Point &Q) const; + const Point& Identity() const; + const Point& Inverse(const Point &P) const; + bool InversionIsFast() const { return true; } + const Point& Add(const Point &P, const Point &Q) const; + const Point& Double(const Point &P) const; + Point ScalarMultiply(const Point &P, const Integer &k) const; + Point CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const; + void SimultaneousMultiply(Point *results, const Point &base, const Integer *exponents, unsigned int exponentsCount) const; + + Point Multiply(const Integer &k, const Point &P) const + { + return ScalarMultiply(P, k); + } + Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const + { + return CascadeScalarMultiply(P, k1, Q, k2); + } + + bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level = 3) const; + bool VerifyPoint(const Point &P) const; + + unsigned int EncodedPointSize(bool compressed = false) const + { + return 1 + (compressed ? 1 : 2)*GetField().MaxElementByteLength(); + } + // returns false if point is compressed and not valid (doesn't check if uncompressed) + bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const; + bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const; + void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const; + void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Point BERDecodePoint(BufferedTransformation &bt) const; + void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Integer FieldSize() const { return GetField().GetModulus(); } + const Field & GetField() const { return *m_fieldPtr; } + const FieldElement & GetA() const { return m_A; } + const FieldElement & GetB() const { return m_B; } + + bool operator==(const ECPM &rhs) const + { + return GetField() == rhs.GetField() && m_A == rhs.m_A && m_B == rhs.m_B; + } + + void operator=(const ECPM &rhs); + +#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562 + virtual ~ECPM() {} +#endif + +private: + inline Point WeierstrassToMontgomery(const Point& In) const; + inline Point MontgomeryToWeierstrass(const Point& In) const; + + clonable_ptr m_fieldPtr; + clonable_ptr m_ComputeEngine; // does the heavy lifting on the scalar multiplication + FieldElement m_A, m_B; // M_B * y^2 = x^3 + m_A * x^2 + x (mod p) + FieldElement m_AThirds, m_BInv; // for faster conversion, A/3 and 1/B + mutable Point m_R; + +}; + +template class EcPrecomputation; + +//! ECPM precomputation +template<> class EcPrecomputation : public DL_GroupPrecomputation +{ +public: + typedef ECPM EllipticCurve; + + // DL_GroupPrecomputation + bool NeedConversions() const { return true; } + Element ConvertIn(const Element &P) const + { + return P.identity ? P : ECPM::Point(m_ec->GetField().ConvertIn(P.x), m_ec->GetField().ConvertIn(P.y)); + }; + Element ConvertOut(const Element &P) const + { + return P.identity ? P : ECPM::Point(m_ec->GetField().ConvertOut(P.x), m_ec->GetField().ConvertOut(P.y)); + } + const AbstractGroup & GetGroup() const { return *m_ec; } + Element BERDecodeElement(BufferedTransformation &bt) const { return m_ec->BERDecodePoint(bt); } + void DEREncodeElement(BufferedTransformation &bt, const Element &v) const { m_ec->DEREncodePoint(bt, v, false); } + + // non-inherited + void SetCurve(const ECPM &ec) + { + m_ec.reset(new ECPM(ec, true)); + m_ecOriginal = ec; + } + const ECPM & GetCurve() const { return *m_ecOriginal; } + +#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562 + virtual ~EcPrecomputation() {} +#endif + +private: + value_ptr m_ec, m_ecOriginal; +}; + +NAMESPACE_END + +#endif \ No newline at end of file diff --git a/oids.h b/oids.h index 4ce6546d..030606c0 100644 --- a/oids.h +++ b/oids.h @@ -48,6 +48,32 @@ DEFINE_OID(1, iso) DEFINE_OID(oiw()+3, oiw_secsig); DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms); DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1); + DEFINE_OID(identified_organization() + 6, dod); + DEFINE_OID(dod() + 1, dod_internet); + DEFINE_OID(dod_internet() + 4, dod_internet_private); + DEFINE_OID(dod_internet_private() + 1, dod_internet_private_enterprise); + DEFINE_OID(dod_internet_private_enterprise() + 9509, denis_bider); + DEFINE_OID(denis_bider() + 5, cryptopp); // denis bider provided us with this OID root, see https://github.com/weidai11/cryptopp/issues/67#issuecomment-160915245 + DEFINE_OID(cryptopp() + 1, cryptopp_montgomery_curves); + // see http://safecurves.cr.yp.to/equation.html for the curves + DEFINE_OID(cryptopp_montgomery_curves() + 1, cryptoppM221); + DEFINE_OID(cryptopp_montgomery_curves() + 2, cryptoppM383); + DEFINE_OID(cryptopp_montgomery_curves() + 3, cryptoppM511); + DEFINE_OID(cryptopp_montgomery_curves() + 4, cryptoppCurve383187); + DEFINE_OID(cryptopp() + 2, cryptopp_edwards_curves); + DEFINE_OID(cryptopp_edwards_curves() + 1, cryptoppE222); + DEFINE_OID(cryptopp_edwards_curves() + 2, cryptoppE382); + DEFINE_OID(cryptopp_edwards_curves() + 3, cryptoppEd448); + DEFINE_OID(cryptopp_edwards_curves() + 4, cryptoppE521); + DEFINE_OID(cryptopp_edwards_curves() + 5, cryptoppCurve1174); + DEFINE_OID(cryptopp_edwards_curves() + 6, cryptoppCurve41417); + DEFINE_OID(dod_internet_private_enterprise() + 11591, gnu); + DEFINE_OID(gnu() + 15, gnu_elliptic_curve); + // as per https://tools.ietf.org/html/draft-josefsson-pkix-newcurves + DEFINE_OID(gnu_elliptic_curve() + 1, ietfCurve25519); + DEFINE_OID(gnu_elliptic_curve() + 2, ietfCurve448); + DEFINE_OID(gnu_elliptic_curve() + 3, ietfCurve25519ph); + DEFINE_OID(gnu_elliptic_curve() + 4, ietfCurve448ph); DEFINE_OID(identified_organization()+36, teletrust); DEFINE_OID(teletrust()+3, teletrust_algorithm) diff --git a/test.cpp b/test.cpp index a6a27005..88fbd250 100644 --- a/test.cpp +++ b/test.cpp @@ -937,6 +937,7 @@ bool Validate(int alg, bool thorough, const char *seedInput) case 68: result = ValidateGCM(); break; case 69: result = ValidateCMAC(); break; case 70: result = ValidateHKDF(); break; + case 71: result = ValidateECPM(); break; default: return false; } diff --git a/validat1.cpp b/validat1.cpp index 892dcc81..720fb195 100644 --- a/validat1.cpp +++ b/validat1.cpp @@ -144,6 +144,7 @@ bool ValidateAll(bool thorough) pass=ValidateRW() && pass; // pass=ValidateBlumGoldwasser() && pass; pass=ValidateECP() && pass; + pass = ValidateECPM() && pass; pass=ValidateEC2N() && pass; pass=ValidateECDSA() && pass; pass=ValidateESIGN() && pass; diff --git a/validat2.cpp b/validat2.cpp index fd6d244a..e7b0c9b2 100644 --- a/validat2.cpp +++ b/validat2.cpp @@ -26,6 +26,7 @@ #include "integer.h" #include "gf2n.h" #include "ecp.h" +#include "ecpm.h" #include "ec2n.h" #include "asn.h" #include "rng.h" @@ -715,6 +716,112 @@ bool ValidateECP() return pass; } +bool ValidateECPM() +{ + cout << "\nECPM validation suite running...\n\n"; + + ECIES ::Decryptor cpriv(GlobalRNG(), ASN1::ietfCurve25519()); + ECIES::Encryptor cpub(cpriv); + ByteQueue bq; + cpriv.GetKey().DEREncode(bq); + cpub.AccessKey().AccessGroupParameters().SetEncodeAsOID(true); + cpub.GetKey().DEREncode(bq); + ECDSA::Signer spriv(bq); + ECDSA::Verifier spub(bq); + ECDH::Domain ecdhc(ASN1::ietfCurve25519()); + ECMQV::Domain ecmqvc(ASN1::ietfCurve25519()); + + spriv.AccessKey().Precompute(); + ByteQueue queue; + spriv.AccessKey().SavePrecomputation(queue); + spriv.AccessKey().LoadPrecomputation(queue); + + bool pass = SignatureValidate(spriv, spub); + cpub.AccessKey().Precompute(); + cpriv.AccessKey().Precompute(); + pass = CryptoSystemValidate(cpriv, cpub) && pass; + pass = SimpleKeyAgreementValidate(ecdhc) && pass; + pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass; + + cout << "Turning on point compression..." << endl; + cpriv.AccessKey().AccessGroupParameters().SetPointCompression(true); + cpub.AccessKey().AccessGroupParameters().SetPointCompression(true); + ecdhc.AccessGroupParameters().SetPointCompression(true); + ecmqvc.AccessGroupParameters().SetPointCompression(true); + pass = CryptoSystemValidate(cpriv, cpub) && pass; + pass = SimpleKeyAgreementValidate(ecdhc) && pass; + pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass; + + cout << "Testing recommended montgomery curves..." << endl; + OID oid; + while (!(oid = DL_GroupParameters_EC::GetNextRecommendedParametersOID(oid)).m_values.empty()) + { + DL_GroupParameters_EC params(oid); + bool fail = !params.Validate(GlobalRNG(), 2); + cout << (fail ? "FAILED" : "passed") << " " << dec << params.GetCurve().GetField().MaxElementBitLength() << " bits" << endl; + pass = pass && !fail; + } + + /*cout << "Performing the IRTF KATs..." << endl; + + // tests from page 10 of IRTF curves draft 11 + // calculate the y coordinates for the test + DL_GroupParameters_EC Curve25519(ASN1::ietfCurve25519()); + const char* KAT_Base_25519_1 = "0231029842492115040904895560451863089656472772604678260265531221036453811406496"; + const char* KAT_Base_25519_2 = "02e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493"; + StringSource SS25519KAT_1(KAT_Base_25519_1,true,new HexDecoder); + StringSource SS25519KAT_2(KAT_Base_25519_2, true, new HexDecoder); + Integer() + ECPPoint P_KAT_Base_25519_1, P_KAT_Base_25519_2; + Curve25519.GetCurve().DecodePoint(P_KAT_Base_25519_1, SS25519KAT_1, 67); + Curve25519.GetCurve().DecodePoint(P_KAT_Base_25519_2, SS25519KAT_2, 67); + Integer x125519("0xe6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c"); + Integer x225519("0xe5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493"); + Integer BInv25519 = Curve25519.GetCurve().GetField().MultiplicativeInverse(Curve25519.GetCurve().GetB()); + Integer y125519 = (x125519*BInv25519*(x125519*(x125519 + Curve25519.GetCurve().GetA()) + 1)) % Curve25519.GetCurve().GetField().GetModulus(); + y125519 = ModularSquareRoot(y125519, Curve25519.GetCurve().GetField().GetModulus()); + Integer y225519 = (x225519*BInv25519*(x225519*(x225519 + Curve25519.GetCurve().GetA()) + 1)) % Curve25519.GetCurve().GetField().GetModulus(); + y225519 = ModularSquareRoot(y225519, Curve25519.GetCurve().GetField().GetModulus()); + + cout < Curve448(ASN1::ietfCurve448()); + Integer x1448("0x06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086"); + Integer x2448("0x0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db"); + Integer BInv448 = Curve448.GetCurve().GetField().MultiplicativeInverse(Curve448.GetCurve().GetB()); + Integer y1448 = (x1448*BInv448*(x1448*(x1448 + Curve448.GetCurve().GetA()) + 1)) % Curve448.GetCurve().GetField().GetModulus(); + y1448 = ModularSquareRoot(y1448, Curve448.GetCurve().GetField().GetModulus()); + Integer y2448 = (x2448*BInv448*(x2448*(x2448 + Curve448.GetCurve().GetA()) + 1)) % Curve448.GetCurve().GetField().GetModulus(); + y2448 = ModularSquareRoot(y2448, Curve448.GetCurve().GetField().GetModulus()); + + ECPPoint Test1448 = Curve448.ExponentiateElement(ECPPoint(x1448, y1448), Integer("0x3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3")); + ECPPoint Test2448 = Curve448.ExponentiateElement(ECPPoint(x2448, y2448), Integer("0x203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f")); + + Integer Result1448("0xce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f"); + Integer Result2448("0x884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d"); + + pass = pass && (Result1448 == Test1448.x); + pass = pass && (Result2448 == Test2448.x); + failedKATs = failedKATs || (Result1448 != Test1448.x); + failedKATs = failedKATs || (Result2448 != Test2448.x); + + cout << (failedKATs ? "FAILED" : "passed") << " " << "known anser tests" << endl;*/ + + return pass; +} + bool ValidateEC2N() { cout << "\nEC2N validation suite running...\n\n"; diff --git a/validate.h b/validate.h index 898df436..d979bd8a 100644 --- a/validate.h +++ b/validate.h @@ -81,6 +81,7 @@ bool ValidateRabin(); bool ValidateRW(); //bool ValidateBlumGoldwasser(); bool ValidateECP(); +bool ValidateECPM(); bool ValidateEC2N(); bool ValidateECDSA(); bool ValidateESIGN(); From 62c819c162bacd95cb621434539d5801e0826574 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Tue, 12 Jan 2016 21:17:11 +0100 Subject: [PATCH 02/21] Added the ecpm files to the file list, This should make these changes compatible with the makefile; VS project files aren't supported yet --- Filelist.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Filelist.txt b/Filelist.txt index e55b1041..8a07bbb4 100644 --- a/Filelist.txt +++ b/Filelist.txt @@ -92,6 +92,8 @@ eccrypto.cpp eccrypto.h ecp.cpp ecp.h +ecpm.cpp +ecpm.h elgamal.cpp elgamal.h emsa2.cpp From f8d5d8274edf7918d1ec2c91720c1227af4a75c7 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Tue, 12 Jan 2016 21:53:56 +0100 Subject: [PATCH 03/21] Update integer.h --- integer.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/integer.h b/integer.h index 858b1cdb..17f651c7 100644 --- a/integer.h +++ b/integer.h @@ -101,27 +101,31 @@ public: //! \brief Convert from a C-string //! \param str C-string value + //! \param order byte order //! \details \p str can be in base 2, 8, 10, or 16. Base is determined by a case //! insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10. - explicit Integer(const char *str); + explicit Integer(const char *str, ByteOrder order = BIG_ENDIAN_ORDER); //! \brief Convert from a wide C-string //! \param str wide C-string value + //! \param order byte order //! \details \p str can be in base 2, 8, 10, or 16. Base is determined by a case //! insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10. - explicit Integer(const wchar_t *str); + explicit Integer(const wchar_t *str, ByteOrder order = BIG_ENDIAN_ORDER); //! \brief Convert from a big-endian byte array //! \param encodedInteger big-endian byte array //! \param byteCount length of the byte array //! \param sign enumeration indicating Signedness - Integer(const byte *encodedInteger, size_t byteCount, Signedness sign=UNSIGNED); + //! \param order byte order + Integer(const byte *encodedInteger, size_t byteCount, Signedness sign=UNSIGNED, ByteOrder order = BIG_ENDIAN_ORDER); //! \brief Convert from a big-endian array //! \param bt BufferedTransformation object with big-endian byte array //! \param byteCount length of the byte array //! \param sign enumeration indicating Signedness - Integer(BufferedTransformation &bt, size_t byteCount, Signedness sign=UNSIGNED); + //! \param order byte order + Integer(BufferedTransformation &bt, size_t byteCount, Signedness sign=UNSIGNED, ByteOrder order = BIG_ENDIAN_ORDER); //! \brief Convert from a BER encoded byte array //! \param bt BufferedTransformation object with BER encoded byte array From 36f5e4c4c86905825a88acba745245b9d5092020 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 22:38:56 +0100 Subject: [PATCH 04/21] updated to offer the option to hide the base Added the config.h related changes of the Integer patch (show_no_base only) --- config.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config.h b/config.h index 8a26dd0a..6563194e 100644 --- a/config.h +++ b/config.h @@ -86,6 +86,14 @@ // CACM paper. // #define LCRNG_ORIGINAL_NUMBERS +// Define this if you want Integer's operator<< to honor std::showbase (and +// std::noshowbase). If defined, Integer will use a suffix of 'b', 'o', 'h' +// or '.' (the last for decimal) when std::showbase is in effect. If +// std::noshowbase is set, then the suffix is not added to the Integer. If +// not defined, existing behavior is preserved and Integer will use a suffix +// of 'b', 'o', 'h' or '.' (the last for decimal). +// #define CRYPTOPP_USE_STD_SHOWBASE + // choose which style of sockets to wrap (mostly useful for MinGW which has both) #if !defined(NO_BERKELEY_STYLE_SOCKETS) && !defined(PREFER_BERKELEY_STYLE_SOCKETS) # define PREFER_BERKELEY_STYLE_SOCKETS From 082a348b8e2afd9948f5e0ffe657e6d28623b3cd Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 22:39:49 +0100 Subject: [PATCH 05/21] synced against config.h --- config.recommend | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config.recommend b/config.recommend index bc933a0b..8fe2e84c 100644 --- a/config.recommend +++ b/config.recommend @@ -86,6 +86,14 @@ // CACM paper. // #define LCRNG_ORIGINAL_NUMBERS +// Define this if you want Integer's operator<< to honor std::showbase (and +// std::noshowbase). If defined, Integer will use a suffix of 'b', 'o', 'h' +// or '.' (the last for decimal) when std::showbase is in effect. If +// std::noshowbase is set, then the suffix is not added to the Integer. If +// not defined, existing behavior is preserved and Integer will use a suffix +// of 'b', 'o', 'h' or '.' (the last for decimal). +// #define CRYPTOPP_USE_STD_SHOWBASE + // choose which style of sockets to wrap (mostly useful for MinGW which has both) #if !defined(NO_BERKELEY_STYLE_SOCKETS) && !defined(PREFER_BERKELEY_STYLE_SOCKETS) # define PREFER_BERKELEY_STYLE_SOCKETS From ba0ce02134ffc5a41dbc86d023553a0a4b4e011a Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 22:42:52 +0100 Subject: [PATCH 06/21] added std::showbase support applied the std::showbase part of the integer patch --- integer.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/integer.cpp b/integer.cpp index de5df007..bf02cf8d 100644 --- a/integer.cpp +++ b/integer.cpp @@ -3483,7 +3483,14 @@ std::ostream& operator<<(std::ostream& out, const Integer &a) // out << ","; } - return out << suffix; +#ifdef CRYPTOPP_USE_STD_SHOWBASE + if(out.flags() & std::ios_base::showbase) + out << suffix; + + return out; +#else + return out << suffix; +#endif } Integer& Integer::operator++() From ea980e5ec05a19076d8e4c22cb8e116bd7b442ae Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:19:49 +0100 Subject: [PATCH 07/21] applied main changes applied main changes from the Integer Patch --- integer.cpp | 118 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 23 deletions(-) diff --git a/integer.cpp b/integer.cpp index bf02cf8d..bebbf1b8 100644 --- a/integer.cpp +++ b/integer.cpp @@ -3021,7 +3021,7 @@ Integer::Integer(word value, size_t length) template static Integer StringToInteger(const T *str) { - int radix; + int radix, sign = 1; // GCC workaround // std::char_traits::length() not defined in GCC 3.2 and STLport 4.5.3 unsigned int length; @@ -3030,7 +3030,7 @@ static Integer StringToInteger(const T *str) Integer v; if (length == 0) - return v; + return Integer::Zero(); switch (str[length-1]) { @@ -3050,30 +3050,102 @@ static Integer StringToInteger(const T *str) radix=10; } - if (length > 2 && str[0] == '0' && str[1] == 'x') - radix = 16; - - for (unsigned i=0; i= '0' && str[i] <= '9') - digit = str[i] - '0'; - else if (str[i] >= 'A' && str[i] <= 'F') - digit = str[i] - 'A' + 10; - else if (str[i] >= 'a' && str[i] <= 'f') - digit = str[i] - 'a' + 10; - else - digit = radix; - - if (digit < radix) - { - v *= radix; - v += digit; - } + sign = -1; + str += 1, length -= 1; } - if (str[0] == '-') + if (length > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + { + radix = 16; + str += 2, length -= 2; + } + + if(radix == 16 && order == LITTLE_ENDIAN_ORDER) + { + // Nibble high, low and count + unsigned int nh, nl, nc = 0; + Integer position(Integer::One()); + + for (unsigned int i=0; i(str[i]); + + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else + digit = radix; + + if (digit < radix) + { + if(nc++ == 0) + nh = digit; + else + nl = digit; + + if(nc == 2) + { + v += position * (nh << 4 | nl); + nc = 0, position <<= 8; + } + } + } + + if(nc == 1) + v += nh * position; + } + else if(order == LITTLE_ENDIAN_ORDER) + { + for (int i=static_cast(length)-1; i>=0; i--) + { + int digit, ch = static_cast(str[i]); + + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else + digit = radix; + + if (digit < radix) + { + v *= radix; + v += digit; + } + } + } + else + { + for (unsigned int i=0; i(str[i]); + + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else + digit = radix; + + if (digit < radix) + { + v *= radix; + v += digit; + } + } + } + + if (sign == -1) v.Negate(); return v; From fb9da4e0435f4cc413d3c81dd4a7e14d54b4416c Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:24:39 +0100 Subject: [PATCH 08/21] finalized patch added final components of the Integer patch --- integer.cpp | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/integer.cpp b/integer.cpp index bebbf1b8..428623c7 100644 --- a/integer.cpp +++ b/integer.cpp @@ -2871,13 +2871,36 @@ signed long Integer::ConvertToLong() const return sign==POSITIVE ? value : -(signed long)value; } -Integer::Integer(BufferedTransformation &encodedInteger, size_t byteCount, Signedness s) +Integer::Integer(BufferedTransformation &encodedInteger, size_t byteCount, Signedness s, ByteOrder o) { + assert(o == BIG_ENDIAN_ORDER || o == LITTLE_ENDIAN_ORDER); + + if(o == LITTLE_ENDIAN_ORDER) + { + SecByteBlock block(byteCount); + encodedInteger.Get(block, block.size()); + std::reverse(block.begin(), block.begin()+block.size()); + + Decode(block.begin(), block.size(), s); + return; + } + Decode(encodedInteger, byteCount, s); } -Integer::Integer(const byte *encodedInteger, size_t byteCount, Signedness s) +Integer::Integer(const byte *encodedInteger, size_t byteCount, Signedness s, ByteOrder o) { + assert(o == BIG_ENDIAN_ORDER || o == LITTLE_ENDIAN_ORDER); + + if(o == LITTLE_ENDIAN_ORDER) + { + SecByteBlock block(byteCount); + std::reverse_copy(encodedInteger, encodedInteger+byteCount, block.begin()); + + Decode(block.begin(), block.size(), s); + return; + } + Decode(encodedInteger, byteCount, s); } @@ -3019,8 +3042,10 @@ Integer::Integer(word value, size_t length) } template -static Integer StringToInteger(const T *str) +static Integer StringToInteger(const T *str, ByteOrder order) { + assert(order == LITTLE_ENDIAN_ORDER || order == BIG_ENDIAN_ORDER); + int radix, sign = 1; // GCC workaround // std::char_traits::length() not defined in GCC 3.2 and STLport 4.5.3 @@ -3151,16 +3176,16 @@ static Integer StringToInteger(const T *str) return v; } -Integer::Integer(const char *str) +Integer::Integer(const char *str, ByteOrder order) : reg(2), sign(POSITIVE) { - *this = StringToInteger(str); + *this = StringToInteger(str,order); } -Integer::Integer(const wchar_t *str) +Integer::Integer(const wchar_t *str, ByteOrder order) : reg(2), sign(POSITIVE) { - *this = StringToInteger(str); + *this = StringToInteger(str,order); } unsigned int Integer::WordCount() const From 2e1cc51b4137ea696948e54cb251a2746fb6ac08 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:37:09 +0100 Subject: [PATCH 09/21] removed ecpm, not part of this branch --- Filelist.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/Filelist.txt b/Filelist.txt index 8a07bbb4..e55b1041 100644 --- a/Filelist.txt +++ b/Filelist.txt @@ -92,8 +92,6 @@ eccrypto.cpp eccrypto.h ecp.cpp ecp.h -ecpm.cpp -ecpm.h elgamal.cpp elgamal.h emsa2.cpp From 53f97c16d504e1b871fe771d440b4c7ff9eac2d1 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:37:42 +0100 Subject: [PATCH 10/21] Delete ecpm.h --- ecpm.h | 142 --------------------------------------------------------- 1 file changed, 142 deletions(-) delete mode 100644 ecpm.h diff --git a/ecpm.h b/ecpm.h deleted file mode 100644 index f23a9dda..00000000 --- a/ecpm.h +++ /dev/null @@ -1,142 +0,0 @@ -// ecpm.h - written and placed in public domain by Jean-Pierre Muench. Copyright assigned to Crypto++ project. - -//! \file ecpm.h -//! \brief Classes for montgomery curves over prime fields - -#ifndef CRYPTOPP_ECPM_H -#define CRYPTOPP_ECPM_H - -#include "cryptlib.h" -#include "integer.h" -#include "modarith.h" -#include "eprecomp.h" -#include "smartptr.h" -#include "pubkey.h" -#include "ecp.h" - -NAMESPACE_BEGIN(CryptoPP) - -// strategy: -// first do it the conservative way: each SimultaneousMultiply is followed and preceeded by a transformation -// later replace this algorithm using an optimized algorithm using the Montgomery Ladder -class CRYPTOPP_DLL ECPM : public AbstractGroup -{ -public: - typedef ModularArithmetic Field; - typedef Integer FieldElement; - typedef ECPPoint Point; - - ECPM() {} - ECPM(const ECPM &ecp, bool convertToMontgomeryRepresentation = false); - ECPM(const Integer &modulus, const FieldElement &A, const FieldElement &B); - // construct from BER encoded parameters - // this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters - ECPM(BufferedTransformation &bt); - - // encode the fields fieldID and curve of the sequence ECParameters - void DEREncode(BufferedTransformation &bt) const; - - bool Equal(const Point &P, const Point &Q) const; - const Point& Identity() const; - const Point& Inverse(const Point &P) const; - bool InversionIsFast() const { return true; } - const Point& Add(const Point &P, const Point &Q) const; - const Point& Double(const Point &P) const; - Point ScalarMultiply(const Point &P, const Integer &k) const; - Point CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const; - void SimultaneousMultiply(Point *results, const Point &base, const Integer *exponents, unsigned int exponentsCount) const; - - Point Multiply(const Integer &k, const Point &P) const - { - return ScalarMultiply(P, k); - } - Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const - { - return CascadeScalarMultiply(P, k1, Q, k2); - } - - bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level = 3) const; - bool VerifyPoint(const Point &P) const; - - unsigned int EncodedPointSize(bool compressed = false) const - { - return 1 + (compressed ? 1 : 2)*GetField().MaxElementByteLength(); - } - // returns false if point is compressed and not valid (doesn't check if uncompressed) - bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const; - bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const; - void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const; - void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; - - Point BERDecodePoint(BufferedTransformation &bt) const; - void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; - - Integer FieldSize() const { return GetField().GetModulus(); } - const Field & GetField() const { return *m_fieldPtr; } - const FieldElement & GetA() const { return m_A; } - const FieldElement & GetB() const { return m_B; } - - bool operator==(const ECPM &rhs) const - { - return GetField() == rhs.GetField() && m_A == rhs.m_A && m_B == rhs.m_B; - } - - void operator=(const ECPM &rhs); - -#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562 - virtual ~ECPM() {} -#endif - -private: - inline Point WeierstrassToMontgomery(const Point& In) const; - inline Point MontgomeryToWeierstrass(const Point& In) const; - - clonable_ptr m_fieldPtr; - clonable_ptr m_ComputeEngine; // does the heavy lifting on the scalar multiplication - FieldElement m_A, m_B; // M_B * y^2 = x^3 + m_A * x^2 + x (mod p) - FieldElement m_AThirds, m_BInv; // for faster conversion, A/3 and 1/B - mutable Point m_R; - -}; - -template class EcPrecomputation; - -//! ECPM precomputation -template<> class EcPrecomputation : public DL_GroupPrecomputation -{ -public: - typedef ECPM EllipticCurve; - - // DL_GroupPrecomputation - bool NeedConversions() const { return true; } - Element ConvertIn(const Element &P) const - { - return P.identity ? P : ECPM::Point(m_ec->GetField().ConvertIn(P.x), m_ec->GetField().ConvertIn(P.y)); - }; - Element ConvertOut(const Element &P) const - { - return P.identity ? P : ECPM::Point(m_ec->GetField().ConvertOut(P.x), m_ec->GetField().ConvertOut(P.y)); - } - const AbstractGroup & GetGroup() const { return *m_ec; } - Element BERDecodeElement(BufferedTransformation &bt) const { return m_ec->BERDecodePoint(bt); } - void DEREncodeElement(BufferedTransformation &bt, const Element &v) const { m_ec->DEREncodePoint(bt, v, false); } - - // non-inherited - void SetCurve(const ECPM &ec) - { - m_ec.reset(new ECPM(ec, true)); - m_ecOriginal = ec; - } - const ECPM & GetCurve() const { return *m_ecOriginal; } - -#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562 - virtual ~EcPrecomputation() {} -#endif - -private: - value_ptr m_ec, m_ecOriginal; -}; - -NAMESPACE_END - -#endif \ No newline at end of file From a7677527879e56ebef2019c5dbe190b2d5bbd56d Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:38:00 +0100 Subject: [PATCH 11/21] Delete ecpm.cpp --- ecpm.cpp | 396 ------------------------------------------------------- 1 file changed, 396 deletions(-) delete mode 100644 ecpm.cpp diff --git a/ecpm.cpp b/ecpm.cpp deleted file mode 100644 index 163308de..00000000 --- a/ecpm.cpp +++ /dev/null @@ -1,396 +0,0 @@ -// ecpm.cpp - written and placed in public domain by Jean-Pierre Muench. Copyright assigned to the Crypto++ project. - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "ecp.h" -#include "ecpm.h" -#include "asn.h" -#include "integer.h" -#include "nbtheory.h" -#include "modarith.h" -#include "filters.h" -#include "algebra.cpp" - -NAMESPACE_BEGIN(CryptoPP) - -ANONYMOUS_NAMESPACE_BEGIN -static inline ECP::Point ToMontgomery(const ModularArithmetic &mr, const ECP::Point &P) // straight from ecp.cpp -{ - return P.identity ? P : ECP::Point(mr.ConvertIn(P.x), mr.ConvertIn(P.y)); -} - -static inline ECP::Point FromMontgomery(const ModularArithmetic &mr, const ECP::Point &P) // straight from ecp.cpp -{ - return P.identity ? P : ECP::Point(mr.ConvertOut(P.x), mr.ConvertOut(P.y)); -} -static inline ECP* GenerateWeierstrassCurve(const ECPM& MontgomeryCurve) -{ - const Integer& A = MontgomeryCurve.GetA(); - const Integer& B = MontgomeryCurve.GetB(); - const ModularArithmetic& Field = MontgomeryCurve.GetField(); - - // now construct the equivalent Weierstrass curve - // refer to https://crypto.stackexchange.com/q/27842 for the details - // use m_FieldPtr to ensure encoding (eventual Montgomery Representation) is handled correctly - //the transformations also appear independently on http ://safecurves.cr.yp.to/equation.html - - // a = (3-A)/(3B^2) - Integer aWeierstrass = Field.Subtract(3, Field.Square(A)); // a = 3 - A - aWeierstrass = Field.Divide(aWeierstrass, Field.Multiply(3, Field.Square(B))); // a = a / (3B^2) - // b = (2A^3-9A) / (27 B^3) - Integer bWeierstrass = Field.Multiply(A, Field.Subtract(Field.Multiply(2, Field.Square(A)), 9)); // b = A(2A^2-9) - bWeierstrass = Field.Divide(bWeierstrass, Field.Multiply(27, Field.Exponentiate(B, 3))); // b = b / (27 B^3) - - return new ECP(MontgomeryCurve.GetField().GetModulus(), aWeierstrass, bWeierstrass); -} -NAMESPACE_END - -ECPM::ECPM(const Integer &modulus, const FieldElement &A, const FieldElement &B): - m_fieldPtr(new Field(modulus)) -{ - // store A and B for later use - m_A = A.IsNegative() ? (A + modulus) : A;// straight from ecp.cpp - m_B = B.IsNegative() ? (B + modulus) : B;// straight from ecp.cpp - - m_ComputeEngine.reset(GenerateWeierstrassCurve(*this)); - - // to speed up the conversions - m_AThirds = m_fieldPtr->Divide(m_A, 3); - m_BInv = m_fieldPtr->MultiplicativeInverse(m_B); -} - -// straight adaption from ecp.cpp -ECPM::ECPM(const ECPM &ecpm, bool convertToMontgomeryRepresentation) -{ - if (convertToMontgomeryRepresentation && !ecpm.GetField().IsMontgomeryRepresentation()) - { - m_fieldPtr.reset(new MontgomeryRepresentation(ecpm.GetField().GetModulus())); - m_ComputeEngine.reset(new ECP(*ecpm.m_ComputeEngine.get(),convertToMontgomeryRepresentation)); - m_A = GetField().ConvertIn(ecpm.m_A); - m_B = GetField().ConvertIn(ecpm.m_B); - m_AThirds = GetField().ConvertIn(ecpm.m_AThirds); - m_BInv = GetField().ConvertIn(ecpm.m_BInv); - } - else - operator=(ecpm); -} - -ECPM::ECPM(BufferedTransformation &bt) - : m_fieldPtr(new Field(bt)) -{ - BERSequenceDecoder seq(bt); - GetField().BERDecodeElement(seq, m_A); - GetField().BERDecodeElement(seq, m_B); - // skip optional seed - if (!seq.EndReached()) - { - SecByteBlock seed; - unsigned int unused; - BERDecodeBitString(seq, seed, unused); - } - seq.MessageEnd(); - - m_ComputeEngine.reset(GenerateWeierstrassCurve(*this)); - - m_AThirds = m_fieldPtr->Divide(m_A, 3); - m_BInv = m_fieldPtr->MultiplicativeInverse(m_B); -} - -// straight adaption from ecp.cpp -void ECPM::DEREncode(BufferedTransformation &bt) const -{ - GetField().DEREncode(bt); - DERSequenceEncoder seq(bt); - GetField().DEREncodeElement(seq, m_A); - GetField().DEREncodeElement(seq, m_B); - seq.MessageEnd(); -} - -// straight adaption from ecp.cpp -bool ECPM::DecodePoint(ECPM::Point &P, const byte *encodedPoint, size_t encodedPointLen) const -{ - StringStore store(encodedPoint, encodedPointLen); - return DecodePoint(P, store, encodedPointLen); -} - -// straight adaption from ecp.cpp -bool ECPM::DecodePoint(ECPM::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const -{ - byte type; - if (encodedPointLen < 1 || !bt.Get(type)) - return false; - - switch (type) - { - case 0: - P.identity = true; - return true; - case 2: - case 3: - { - if (encodedPointLen != EncodedPointSize(true)) - return false; - - Integer p = FieldSize(); - - P.identity = false; - P.x.Decode(bt, GetField().MaxElementByteLength()); - // curve is: By^2=x^3+Ax^2+x <=> y=sqrt(x/B(x(A+x)+1) - P.y = (m_BInv * P.x *(P.x * (P.x + m_A) + Integer::One()))%p; - - if (Jacobi(P.y, p) != 1) - return false; - - P.y = ModularSquareRoot(P.y, p); - - if ((type & 1) != P.y.GetBit(0)) - P.y = p - P.y; - - return true; - } - case 4: - { - if (encodedPointLen != EncodedPointSize(false)) - return false; - - unsigned int len = GetField().MaxElementByteLength(); - P.identity = false; - P.x.Decode(bt, len); - P.y.Decode(bt, len); - return true; - } - default: - return false; - } -} - -// straight adaption from ecp.cpp -void ECPM::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const -{ - if (P.identity) - NullStore().TransferTo(bt, EncodedPointSize(compressed)); - else if (compressed) - { - bt.Put(2 + P.y.GetBit(0)); - P.x.Encode(bt, GetField().MaxElementByteLength()); - } - else - { - unsigned int len = GetField().MaxElementByteLength(); - bt.Put(4); // uncompressed - P.x.Encode(bt, len); - P.y.Encode(bt, len); - } -} - -// straight adaption from ecp.cpp -void ECPM::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const -{ - ArraySink sink(encodedPoint, EncodedPointSize(compressed)); - EncodePoint(sink, P, compressed); - assert(sink.TotalPutLength() == EncodedPointSize(compressed)); -} - -// straight adaption from ecp.cpp -ECPM::Point ECPM::BERDecodePoint(BufferedTransformation &bt) const -{ - SecByteBlock str; - BERDecodeOctetString(bt, str); - Point P; - if (!DecodePoint(P, str, str.size())) - BERDecodeError(); - return P; -} - -// straight adaption from ecp.cpp -void ECPM::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const -{ - SecByteBlock str(EncodedPointSize(compressed)); - EncodePoint(str, P, compressed); - DEREncodeOctetString(bt, str); -} - -// straight adaption from ecp.cpp -bool ECPM::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const -{ - Integer p = FieldSize(); - - bool pass = p.IsOdd(); - pass = pass && !m_A.IsNegative() && m_A

= 1) - pass = pass && ((m_B * (m_A * m_A - 4)) % p).IsPositive(); - - if (level >= 2) - pass = pass && VerifyPrime(rng, p); - - return pass; -} - -// straight adaption from ecp.cpp -bool ECPM::VerifyPoint(const Point &P) const -{ - const FieldElement &x = P.x, &y = P.y; - Integer p = FieldSize(); - - // use the field arithmetic here, in case our data is in Montgomery form - // ecp.cpp does this with plain integer arithmetic -> will fail if montgomery representation is on, but was never called when montgomery representation was on - const FieldElement IsOnCurve = m_fieldPtr->Subtract(m_fieldPtr->Multiply(x,(m_fieldPtr->Add(1,m_fieldPtr->Multiply(x,(m_fieldPtr->Add(m_A,x)))))),m_fieldPtr->Multiply(m_B,m_fieldPtr->Square(y))); - - return P.identity || - (!x.IsNegative() && x

0 == x(1+x(A+x))-By^2 -} - -// straight adaption from ecp.cpp -bool ECPM::Equal(const Point &P, const Point &Q) const -{ - if (P.identity && Q.identity) - return true; - - if (P.identity && !Q.identity) - return false; - - if (!P.identity && Q.identity) - return false; - - return (GetField().Equal(P.x, Q.x) && GetField().Equal(P.y, Q.y)); -} - -// straight adaption from ecp.cpp -const ECPM::Point& ECPM::Identity() const -{ - return Singleton().Ref(); -} - -// straight adaption from ecp.cpp -const ECPM::Point& ECPM::Inverse(const Point &P) const -{ - if (P.identity) - return P; - else - { - m_R.identity = false; - m_R.x = P.x; - m_R.y = GetField().Inverse(P.y); - return m_R; - } -} - -// straight adaption from ecp.cpp -const ECPM::Point& ECPM::Add(const Point &P, const Point &Q) const -{ - if (P.identity) return Q; - if (Q.identity) return P; - if (GetField().Equal(P.x, Q.x)) - return GetField().Equal(P.y, Q.y) ? Double(P) : Identity(); - - FieldElement t = GetField().Subtract(Q.y, P.y); // t = y_Q - y_P - t = GetField().Divide(t, GetField().Subtract(Q.x, P.x)); // t = (y_Q - y_P) / (x_Q - x_P) - FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Subtract(GetField().Multiply(m_B,GetField().Square(t)), P.x), Q.x),m_A); // x = B*t^2-x_P-x_Q-A - m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); // y = t * (x_P - x) - y_P - - m_R.x.swap(x); - m_R.identity = false; - return m_R; -} - -// straight adaption from ecp.cpp -const ECPM::Point& ECPM::Double(const Point &P) const -{ - if (P.identity || P.y == GetField().Identity()) return Identity(); - - FieldElement t = GetField().Add(GetField().Double(P.x), P.x);// t = 2x_P + x_P = 3x_P - t = GetField().Add(GetField().Multiply(P.x,GetField().Add(t,GetField().Double(m_A))), GetField().ConvertIn(1)); // x_P * ( t + 2 * A)+1 - FieldElement h1= GetField().Multiply(t, m_BInv), h2= GetField().Double(P.y); // put this in two steps or it fails somehow otherwise - t = GetField().Divide(h1, h2); // t = (x_P(3x_P + 2A)+1)/(2B*y_P) - FieldElement& x = m_R.x; - x = GetField().Multiply(m_B, GetField().Square(t)); // put this in two steps or it fails somehow otherwise - x = GetField().Subtract(GetField().Subtract(x, GetField().Double(P.x)), m_A); // x = B * t^2 - A - x_1 - x_2 - m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); // t (x_P - x) -y_P - - m_R.identity = false; - return m_R; -} - -// straight adaption from ecp.cpp -ECPM::Point ECPM::ScalarMultiply(const Point &P, const Integer &k) const -{ - Element result; - if (k.BitCount() <= 5) - AbstractGroup::SimultaneousMultiply(&result, P, &k, 1); - else - ECPM::SimultaneousMultiply(&result, P, &k, 1); - - return result; -} - -// this is probably the cause of the issue -void ECPM::SimultaneousMultiply(ECPM::Point *results, const ECPM::Point &P, const Integer *expBegin, unsigned int expCount) const -{ - Point ConvertedBase = MontgomeryToWeierstrass(P); - // let the compute engine do its optimized work - m_ComputeEngine->SimultaneousMultiply(results, ConvertedBase, expBegin, expCount); - - // fetch the results and convert them back to our preferred form - for (unsigned int i = 0; i < expCount; ++i) - results[i] = WeierstrassToMontgomery(results[i]); - - return; - - // implement Montgomery ladder below -} - -// straight adaption from ecp.cpp -ECPM::Point ECPM::CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const -{ - if (!GetField().IsMontgomeryRepresentation()) - { - ECPM ecpmr(*this, true); - const ModularArithmetic &mr = ecpmr.GetField(); - return FromMontgomery(mr, ecpmr.CascadeScalarMultiply(ToMontgomery(mr, P), k1, ToMontgomery(mr, Q), k2)); - } - else - return AbstractGroup::CascadeScalarMultiply(P, k1, Q, k2); -} - -// added as ECP doesn't offer a Clone() function which is required for assignment -void ECPM::operator=(const ECPM& rhs) -{ - m_A = rhs.m_A; - m_AThirds = rhs.m_AThirds; - m_B = rhs.m_B; - m_BInv = rhs.m_BInv; - m_fieldPtr = rhs.m_fieldPtr->Clone(); - m_ComputeEngine.reset(new ECP(*rhs.m_ComputeEngine,rhs.m_ComputeEngine->GetField().IsMontgomeryRepresentation())); -} - -// converts weierstrass points to montgomery points -// it can be checked at https://crypto.stackexchange.com/q/27842 and http://safecurves.cr.yp.to/equation.html -inline ECPM::Point ECPM::WeierstrassToMontgomery(const Point& In) const -{ - // (x,y) -> (Bx-A/3,By) - ECPPoint Out; - Out.identity = In.identity; - Out.x = GetField().Subtract(m_fieldPtr->Multiply(m_B,In.x),m_AThirds); - Out.y = GetField().Multiply(In.y,m_B); - return Out; -} - -// converts weierstrass points to montgomery points, the math *should* be right -inline ECPM::Point ECPM::MontgomeryToWeierstrass(const Point& In) const -{ - // (x,y) -> ((x+A/3)/B,y/B) - ECPPoint Out; - Out.identity = In.identity; - Out.x = GetField().Multiply(m_fieldPtr->Add(In.x,m_AThirds),m_BInv); - Out.y = GetField().Multiply(In.y, m_BInv); - return Out; -} - -NAMESPACE_END - -#endif From 53248fc4a3e922a93cda619fe515cd5ff4a52326 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:39:11 +0100 Subject: [PATCH 12/21] removed ECPM code --- eccrypto.cpp | 70 ---------------------------------------------------- 1 file changed, 70 deletions(-) diff --git a/eccrypto.cpp b/eccrypto.cpp index 3e39d92f..3ac4f194 100644 --- a/eccrypto.cpp +++ b/eccrypto.cpp @@ -122,24 +122,6 @@ template<> struct EcRecommendedParameters unsigned int h; }; -template<> struct EcRecommendedParameters -{ - 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) {} - ECPM *NewEC() const - { - StringSource ssP(p, true, new HexDecoder); - StringSource ssA(A, true, new HexDecoder); - StringSource ssB(B, true, new HexDecoder); - return new ECPM(Integer(ssP, (size_t)ssP.MaxRetrievable()), ECPM::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), ECPM::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); - }; - - OID oid; - const char *p; - const char *A, *B, *g, *n; - unsigned int h; -}; - struct OIDLessThan { template @@ -448,58 +430,6 @@ static void GetRecommendedParameters(const EcRecommendedParameters *&begin, end = rec + sizeof(rec)/sizeof(rec[0]); } -static void GetRecommendedParameters(const EcRecommendedParameters *&begin, const EcRecommendedParameters *&end) -{ - // this array must be sorted by OID - static const EcRecommendedParameters rec[] = - { - EcRecommendedParameters(ASN1::cryptoppM221(), - "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD", - "0000000000000000000000000000000000000000000000000001C93A", - "00000000000000000000000000000000000000000000000000000001", - "04000000000000000000000000000000000000000000000000000000040F7ACDD2A4939571D1CEF14ECA37C228E61DBFF10707DC6C08C5056D", - "040000000000000000000000000015A08ED730E8A2F77F005042605B", - 8), - EcRecommendedParameters(ASN1::cryptoppM383(), - "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45", - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001F82FE", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C1EC7ED04AAF834AF310E304B2DA0F328E7C165F0E8988ABD3992861290F617AA1F1B2E7D0B6E332E969991B62555E77E", - "10000000000000000000000000000000000000000000000006C79673AC36BA6E7A32576F7B1B249E46BBC225BE9071D7", - 8), - EcRecommendedParameters(ASN1::cryptoppM511(), - "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081806", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052fbdc0ad8530803d28fdbad354bb488d32399ac1cf8f6e01ee3f96389b90c809422b9429e8a43dbf49308ac4455940abe9f1dbca542093a895e30a64af056fa5", - "100000000000000000000000000000000000000000000000000000000000000017B5FEFF30C7F5677AB2AEEBD13779A2AC125042A6AA10BFA54C15BAB76BAF1B", - 8), - EcRecommendedParameters(ASN1::cryptoppCurve383187(), - "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038251", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051EEBE07DC1871896732B12D5504A32370471965C7A11F2C89865F855AB3CBD7C224E3620C31AF3370788457DD5CE46DF", - "1000000000000000000000000000000000000000000000000e85a85287a1488acd41ae84b2b7030446f72088b00a0e21", - 8), - EcRecommendedParameters(ASN1::ietfCurve25519(), - "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED", - "0000000000000000000000000000000000000000000000000000000000076D06", - "0000000000000000000000000000000000000000000000000000000000000001", - "04000000000000000000000000000000000000000000000000000000000000000920AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9", - "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", - 8), - EcRecommendedParameters(ASN1::ietfCurve448(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000262A6", - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057D235D1295F5B1F66C98AB6E58326FCECBAE5D34F55545D060F75DC28DF3F6EDB8027E2346430D211312C4B150677AF76FD7223D457B5B1A", - "3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3", - 4), - }; - begin = rec; - end = rec + sizeof(rec) / sizeof(rec[0]); -} - template OID DL_GroupParameters_EC::GetNextRecommendedParametersOID(const OID &oid) { const EcRecommendedParameters *begin, *end; From 8a766cfe392da74e54a6ecf46020f3bb8e6c40cd Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:39:38 +0100 Subject: [PATCH 13/21] removed ECPM --- eccrypto.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/eccrypto.h b/eccrypto.h index 3adbbf9c..98ee68c2 100644 --- a/eccrypto.h +++ b/eccrypto.h @@ -319,24 +319,20 @@ NAMESPACE_BEGIN(CryptoPP) CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; NAMESPACE_END From a2bd46a843753b6ffc2b92e1ca00eea07245bc82 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:41:27 +0100 Subject: [PATCH 14/21] removed ECPM --- oids.h | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/oids.h b/oids.h index 030606c0..8a397dca 100644 --- a/oids.h +++ b/oids.h @@ -48,33 +48,6 @@ DEFINE_OID(1, iso) DEFINE_OID(oiw()+3, oiw_secsig); DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms); DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1); - DEFINE_OID(identified_organization() + 6, dod); - DEFINE_OID(dod() + 1, dod_internet); - DEFINE_OID(dod_internet() + 4, dod_internet_private); - DEFINE_OID(dod_internet_private() + 1, dod_internet_private_enterprise); - DEFINE_OID(dod_internet_private_enterprise() + 9509, denis_bider); - DEFINE_OID(denis_bider() + 5, cryptopp); // denis bider provided us with this OID root, see https://github.com/weidai11/cryptopp/issues/67#issuecomment-160915245 - DEFINE_OID(cryptopp() + 1, cryptopp_montgomery_curves); - // see http://safecurves.cr.yp.to/equation.html for the curves - DEFINE_OID(cryptopp_montgomery_curves() + 1, cryptoppM221); - DEFINE_OID(cryptopp_montgomery_curves() + 2, cryptoppM383); - DEFINE_OID(cryptopp_montgomery_curves() + 3, cryptoppM511); - DEFINE_OID(cryptopp_montgomery_curves() + 4, cryptoppCurve383187); - DEFINE_OID(cryptopp() + 2, cryptopp_edwards_curves); - DEFINE_OID(cryptopp_edwards_curves() + 1, cryptoppE222); - DEFINE_OID(cryptopp_edwards_curves() + 2, cryptoppE382); - DEFINE_OID(cryptopp_edwards_curves() + 3, cryptoppEd448); - DEFINE_OID(cryptopp_edwards_curves() + 4, cryptoppE521); - DEFINE_OID(cryptopp_edwards_curves() + 5, cryptoppCurve1174); - DEFINE_OID(cryptopp_edwards_curves() + 6, cryptoppCurve41417); - DEFINE_OID(dod_internet_private_enterprise() + 11591, gnu); - DEFINE_OID(gnu() + 15, gnu_elliptic_curve); - // as per https://tools.ietf.org/html/draft-josefsson-pkix-newcurves - DEFINE_OID(gnu_elliptic_curve() + 1, ietfCurve25519); - DEFINE_OID(gnu_elliptic_curve() + 2, ietfCurve448); - DEFINE_OID(gnu_elliptic_curve() + 3, ietfCurve25519ph); - DEFINE_OID(gnu_elliptic_curve() + 4, ietfCurve448ph); - DEFINE_OID(identified_organization()+36, teletrust); DEFINE_OID(teletrust()+3, teletrust_algorithm) DEFINE_OID(teletrust_algorithm()+2+1, id_ripemd160) From 3a0a78e3938f21e79466e938a6aa85555e5b2932 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:42:02 +0100 Subject: [PATCH 15/21] removed ECPM --- test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test.cpp b/test.cpp index 88fbd250..a6a27005 100644 --- a/test.cpp +++ b/test.cpp @@ -937,7 +937,6 @@ bool Validate(int alg, bool thorough, const char *seedInput) case 68: result = ValidateGCM(); break; case 69: result = ValidateCMAC(); break; case 70: result = ValidateHKDF(); break; - case 71: result = ValidateECPM(); break; default: return false; } From 2c45da2354b0bc2b3450297ebc41ead019256ba9 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:42:39 +0100 Subject: [PATCH 16/21] removed ECPM --- validat1.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/validat1.cpp b/validat1.cpp index 720fb195..892dcc81 100644 --- a/validat1.cpp +++ b/validat1.cpp @@ -144,7 +144,6 @@ bool ValidateAll(bool thorough) pass=ValidateRW() && pass; // pass=ValidateBlumGoldwasser() && pass; pass=ValidateECP() && pass; - pass = ValidateECPM() && pass; pass=ValidateEC2N() && pass; pass=ValidateECDSA() && pass; pass=ValidateESIGN() && pass; From a9980a0bc4db9488c7cfcb247d080bb538dc27e0 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:43:17 +0100 Subject: [PATCH 17/21] removed ECPM --- validat2.cpp | 107 --------------------------------------------------- 1 file changed, 107 deletions(-) diff --git a/validat2.cpp b/validat2.cpp index e7b0c9b2..fd6d244a 100644 --- a/validat2.cpp +++ b/validat2.cpp @@ -26,7 +26,6 @@ #include "integer.h" #include "gf2n.h" #include "ecp.h" -#include "ecpm.h" #include "ec2n.h" #include "asn.h" #include "rng.h" @@ -716,112 +715,6 @@ bool ValidateECP() return pass; } -bool ValidateECPM() -{ - cout << "\nECPM validation suite running...\n\n"; - - ECIES ::Decryptor cpriv(GlobalRNG(), ASN1::ietfCurve25519()); - ECIES::Encryptor cpub(cpriv); - ByteQueue bq; - cpriv.GetKey().DEREncode(bq); - cpub.AccessKey().AccessGroupParameters().SetEncodeAsOID(true); - cpub.GetKey().DEREncode(bq); - ECDSA::Signer spriv(bq); - ECDSA::Verifier spub(bq); - ECDH::Domain ecdhc(ASN1::ietfCurve25519()); - ECMQV::Domain ecmqvc(ASN1::ietfCurve25519()); - - spriv.AccessKey().Precompute(); - ByteQueue queue; - spriv.AccessKey().SavePrecomputation(queue); - spriv.AccessKey().LoadPrecomputation(queue); - - bool pass = SignatureValidate(spriv, spub); - cpub.AccessKey().Precompute(); - cpriv.AccessKey().Precompute(); - pass = CryptoSystemValidate(cpriv, cpub) && pass; - pass = SimpleKeyAgreementValidate(ecdhc) && pass; - pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass; - - cout << "Turning on point compression..." << endl; - cpriv.AccessKey().AccessGroupParameters().SetPointCompression(true); - cpub.AccessKey().AccessGroupParameters().SetPointCompression(true); - ecdhc.AccessGroupParameters().SetPointCompression(true); - ecmqvc.AccessGroupParameters().SetPointCompression(true); - pass = CryptoSystemValidate(cpriv, cpub) && pass; - pass = SimpleKeyAgreementValidate(ecdhc) && pass; - pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass; - - cout << "Testing recommended montgomery curves..." << endl; - OID oid; - while (!(oid = DL_GroupParameters_EC::GetNextRecommendedParametersOID(oid)).m_values.empty()) - { - DL_GroupParameters_EC params(oid); - bool fail = !params.Validate(GlobalRNG(), 2); - cout << (fail ? "FAILED" : "passed") << " " << dec << params.GetCurve().GetField().MaxElementBitLength() << " bits" << endl; - pass = pass && !fail; - } - - /*cout << "Performing the IRTF KATs..." << endl; - - // tests from page 10 of IRTF curves draft 11 - // calculate the y coordinates for the test - DL_GroupParameters_EC Curve25519(ASN1::ietfCurve25519()); - const char* KAT_Base_25519_1 = "0231029842492115040904895560451863089656472772604678260265531221036453811406496"; - const char* KAT_Base_25519_2 = "02e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493"; - StringSource SS25519KAT_1(KAT_Base_25519_1,true,new HexDecoder); - StringSource SS25519KAT_2(KAT_Base_25519_2, true, new HexDecoder); - Integer() - ECPPoint P_KAT_Base_25519_1, P_KAT_Base_25519_2; - Curve25519.GetCurve().DecodePoint(P_KAT_Base_25519_1, SS25519KAT_1, 67); - Curve25519.GetCurve().DecodePoint(P_KAT_Base_25519_2, SS25519KAT_2, 67); - Integer x125519("0xe6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c"); - Integer x225519("0xe5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493"); - Integer BInv25519 = Curve25519.GetCurve().GetField().MultiplicativeInverse(Curve25519.GetCurve().GetB()); - Integer y125519 = (x125519*BInv25519*(x125519*(x125519 + Curve25519.GetCurve().GetA()) + 1)) % Curve25519.GetCurve().GetField().GetModulus(); - y125519 = ModularSquareRoot(y125519, Curve25519.GetCurve().GetField().GetModulus()); - Integer y225519 = (x225519*BInv25519*(x225519*(x225519 + Curve25519.GetCurve().GetA()) + 1)) % Curve25519.GetCurve().GetField().GetModulus(); - y225519 = ModularSquareRoot(y225519, Curve25519.GetCurve().GetField().GetModulus()); - - cout < Curve448(ASN1::ietfCurve448()); - Integer x1448("0x06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086"); - Integer x2448("0x0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db"); - Integer BInv448 = Curve448.GetCurve().GetField().MultiplicativeInverse(Curve448.GetCurve().GetB()); - Integer y1448 = (x1448*BInv448*(x1448*(x1448 + Curve448.GetCurve().GetA()) + 1)) % Curve448.GetCurve().GetField().GetModulus(); - y1448 = ModularSquareRoot(y1448, Curve448.GetCurve().GetField().GetModulus()); - Integer y2448 = (x2448*BInv448*(x2448*(x2448 + Curve448.GetCurve().GetA()) + 1)) % Curve448.GetCurve().GetField().GetModulus(); - y2448 = ModularSquareRoot(y2448, Curve448.GetCurve().GetField().GetModulus()); - - ECPPoint Test1448 = Curve448.ExponentiateElement(ECPPoint(x1448, y1448), Integer("0x3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3")); - ECPPoint Test2448 = Curve448.ExponentiateElement(ECPPoint(x2448, y2448), Integer("0x203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f")); - - Integer Result1448("0xce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f"); - Integer Result2448("0x884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d"); - - pass = pass && (Result1448 == Test1448.x); - pass = pass && (Result2448 == Test2448.x); - failedKATs = failedKATs || (Result1448 != Test1448.x); - failedKATs = failedKATs || (Result2448 != Test2448.x); - - cout << (failedKATs ? "FAILED" : "passed") << " " << "known anser tests" << endl;*/ - - return pass; -} - bool ValidateEC2N() { cout << "\nEC2N validation suite running...\n\n"; From a0e615139054cece30201908130015ef45e9ce87 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:43:54 +0100 Subject: [PATCH 18/21] removed ECPM --- validate.h | 1 - 1 file changed, 1 deletion(-) diff --git a/validate.h b/validate.h index d979bd8a..898df436 100644 --- a/validate.h +++ b/validate.h @@ -81,7 +81,6 @@ bool ValidateRabin(); bool ValidateRW(); //bool ValidateBlumGoldwasser(); bool ValidateECP(); -bool ValidateECPM(); bool ValidateEC2N(); bool ValidateECDSA(); bool ValidateESIGN(); From dcbfe822926e1596f59b3fd34cf42c891985fa92 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:45:10 +0100 Subject: [PATCH 19/21] removed ECPM --- eccrypto.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/eccrypto.h b/eccrypto.h index 98ee68c2..a3d15e95 100644 --- a/eccrypto.h +++ b/eccrypto.h @@ -321,12 +321,10 @@ CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; From 1839fc40b3a0e886c9aeabfb31b0870aec94cef5 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Wed, 13 Jan 2016 23:46:05 +0100 Subject: [PATCH 20/21] removed ECPM changes --- oids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/oids.h b/oids.h index 8a397dca..9eac4f10 100644 --- a/oids.h +++ b/oids.h @@ -48,6 +48,7 @@ DEFINE_OID(1, iso) DEFINE_OID(oiw()+3, oiw_secsig); DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms); DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1); + DEFINE_OID(identified_organization()+36, teletrust); DEFINE_OID(teletrust()+3, teletrust_algorithm) DEFINE_OID(teletrust_algorithm()+2+1, id_ripemd160) From 07ff7b0d61bd092886d54c3f23e63947011e7952 Mon Sep 17 00:00:00 2001 From: DevJPM Date: Thu, 14 Jan 2016 12:24:36 +0100 Subject: [PATCH 21/21] moved BE case before LE to improve performance --- integer.cpp | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/integer.cpp b/integer.cpp index 428623c7..c5321680 100644 --- a/integer.cpp +++ b/integer.cpp @@ -3044,7 +3044,7 @@ Integer::Integer(word value, size_t length) template static Integer StringToInteger(const T *str, ByteOrder order) { - assert(order == LITTLE_ENDIAN_ORDER || order == BIG_ENDIAN_ORDER); + assert( order == BIG_ENDIAN_ORDER || order == LITTLE_ENDIAN_ORDER ); int radix, sign = 1; // GCC workaround @@ -3088,7 +3088,29 @@ static Integer StringToInteger(const T *str, ByteOrder order) str += 2, length -= 2; } - if(radix == 16 && order == LITTLE_ENDIAN_ORDER) + if(order == BIG_ENDIAN_ORDER) + { + for (unsigned int i=0; i(str[i]); + + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else + digit = radix; + + if (digit < radix) + { + v *= radix; + v += digit; + } + } + } + else if(radix == 16 && order == LITTLE_ENDIAN_ORDER) { // Nibble high, low and count unsigned int nh, nl, nc = 0; @@ -3125,7 +3147,7 @@ static Integer StringToInteger(const T *str, ByteOrder order) if(nc == 1) v += nh * position; } - else if(order == LITTLE_ENDIAN_ORDER) + else // LITTLE_ENDIAN_ORDER && radix != 16 { for (int i=static_cast(length)-1; i>=0; i--) { @@ -3147,28 +3169,6 @@ static Integer StringToInteger(const T *str, ByteOrder order) } } } - else - { - for (unsigned int i=0; i(str[i]); - - if (ch >= '0' && ch <= '9') - digit = ch - '0'; - else if (ch >= 'A' && ch <= 'F') - digit = ch - 'A' + 10; - else if (ch >= 'a' && ch <= 'f') - digit = ch - 'a' + 10; - else - digit = radix; - - if (digit < radix) - { - v *= radix; - v += digit; - } - } - } if (sign == -1) v.Negate();