diff --git a/xed25519.cpp b/xed25519.cpp index d1461a23..2270aea7 100644 --- a/xed25519.cpp +++ b/xed25519.cpp @@ -47,6 +47,24 @@ const byte blacklist[][32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; +bool HasSmallOrder(const byte y[32]) +{ + // The magic 12 is the count of blaklisted points + byte c[12] = { 0 }; + for (size_t j = 0; j < 32; j++) { + for (size_t i = 0; i < COUNTOF(blacklist); i++) { + c[i] |= y[j] ^ blacklist[i][j]; + } + } + + unsigned int k = 0; + for (size_t i = 0; i < COUNTOF(blacklist); i++) { + k |= (c[i] - 1); + } + + return (bool)((k >> 8) & 1); +} + ANONYMOUS_NAMESPACE_END NAMESPACE_BEGIN(CryptoPP) @@ -120,20 +138,7 @@ bool x25519::IsClamped(const byte x[SECRET_KEYLENGTH]) const bool x25519::IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const { - // The magic 12 is the count of blaklisted points - byte c[12] = { 0 }; - for (size_t j = 0; j < PUBLIC_KEYLENGTH; j++) { - for (size_t i = 0; i < COUNTOF(blacklist); i++) { - c[i] |= y[j] ^ blacklist[i][j]; - } - } - - unsigned int k = 0; - for (size_t i = 0; i < COUNTOF(blacklist); i++) { - k |= (c[i] - 1); - } - - return (bool)((k >> 8) & 1); + return HasSmallOrder(y); } void x25519::BERDecodeAndCheckAlgorithmID(BufferedTransformation &bt) @@ -360,6 +365,11 @@ bool ed25519PrivateKey::IsClamped(const byte x[SECRET_KEYLENGTH]) const return (x[0] & 248) == x[0] && (x[31] & 127) == x[31] && (x[31] | 64) == x[31]; } +bool ed25519PrivateKey::IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const +{ + return HasSmallOrder(y); +} + bool ed25519PrivateKey::Validate(RandomNumberGenerator &rng, unsigned int level) const { CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(level); @@ -418,6 +428,9 @@ void ed25519PrivateKey::AssignFrom(const NameValuePairs &source) bool clamp = false; if (source.GetValue("Clamp", clamp) && clamp == true) ClampKeys(m_pk, m_sk); + + CRYPTOPP_ASSERT(IsClamped(m_sk) == true); + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); } void ed25519PrivateKey::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms=g_nullNameValuePairs) @@ -493,6 +506,7 @@ void ed25519PrivateKey::BERDecode(BufferedTransformation &bt) Donna::ed25519_publickey(m_pk, m_sk); CRYPTOPP_ASSERT(IsClamped(m_sk) == true); + CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); } void ed25519PrivateKey::DEREncode(BufferedTransformation &bt, int version) const diff --git a/xed25519.h b/xed25519.h index 3cbc80c5..354d49ae 100644 --- a/xed25519.h +++ b/xed25519.h @@ -450,6 +450,10 @@ struct ed25519PrivateKey : public PKCS8PrivateKey /// \param x private key bool IsClamped(const byte x[SECRET_KEYLENGTH]) const; + /// \brief Test if a key has small order + /// \param y public key + bool IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const; + /// \brief Retrieve private key byte array /// \returns the private key byte array /// \details GetPrivateKeyBytePtr() is used by signing code to call ed25519_sign.