Skip to content

Commit

Permalink
ECC: Removed GenerateNonce() based on rfc-6979. Using only rfc-5869
Browse files Browse the repository at this point in the history
  • Loading branch information
valdok committed Dec 15, 2018
1 parent 0e9a52d commit 6e3217c
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 78 deletions.
80 changes: 22 additions & 58 deletions core/ecc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1197,42 +1197,6 @@ namespace ECC {

} // namespace Tag

/////////////////////
// Nonce and key generation
void GenerateNonce(uintBig& res, const uintBig& sk, const uintBig& msg, const uintBig* pMsg2, uint32_t nAttempt /* = 0 */)
{
for (uint32_t i = 0; ; i++)
{
if (!nonce_function_rfc6979(res.m_pData, msg.m_pData, sk.m_pData, NULL, pMsg2 ? (void*) pMsg2->m_pData : NULL, i))
continue;

if (!nAttempt--)
break;
}
}

void Scalar::Native::GenerateNonceNnz(const uintBig& sk, const uintBig& msg, const uintBig* pMsg2, uint32_t nAttempt /* = 0 */)
{
NoLeak<Scalar> s;

for (uint32_t i = 0; ; i++)
{
ECC::GenerateNonce(s.V.m_Value, sk, msg, pMsg2, i);
if (!ImportNnz(s.V))
continue;

if (!nAttempt--)
break;
}
}

void Scalar::Native::GenerateNonceNnz(const Scalar::Native& sk, const uintBig& msg, const uintBig* pMsg2, uint32_t nAttempt /* = 0 */)
{
NoLeak<Scalar> sk_;
sk_.V = sk;
GenerateNonceNnz(sk_.V.m_Value, msg, pMsg2, nAttempt);
}

/////////////////////
// Key::ID
void Key::ID::get_Hash(Hash::Value& hv) const
Expand Down Expand Up @@ -1322,12 +1286,13 @@ namespace ECC {

/////////////////////
// HKdf
void Rfc5869::Reset(const char* szSalt, uint32_t nSalt, const beam::Blob& ikm)
void Rfc5869::Reset(const char* szSalt, uint32_t nSalt, const beam::Blob& secret, const beam::Blob& ikm)
{
// Extract
Hash::Mac hmac(szSalt, nSalt);
hmac.Write(secret.p, secret.n);
hmac.Write(ikm.p, ikm.n);
hmac >> m_Pkr.V;
hmac >> m_Pkr;

m_bFirstTime = true;
m_Counter = Zero;
Expand All @@ -1337,25 +1302,25 @@ namespace ECC {
void Rfc5869::Next()
{
// Expand
Hash::Mac hmac(m_Pkr.V.m_pData, m_Pkr.V.nBytes);
Hash::Mac hmac(m_Pkr.m_pData, m_Pkr.nBytes);

if (m_bFirstTime)
m_bFirstTime = false;
else
hmac.Write(m_Out.V.m_pData, m_Out.V.nBytes);
hmac.Write(m_Out.m_pData, m_Out.nBytes);

hmac.Write(m_Context.p, m_Context.n);

m_Counter.Inc();
hmac.Write(m_Counter.m_pData, m_Counter.nBytes);

hmac >> m_Out.V;
hmac >> m_Out;
}

void Rfc5869::operator >> (Scalar::Native& sk)
{
static_assert(sizeof(Scalar) == sizeof(m_Out.V), "");
const Scalar& s = reinterpret_cast<const Scalar&>(m_Out.V);
static_assert(sizeof(Scalar) == sizeof(m_Out), "");
const Scalar& s = reinterpret_cast<const Scalar&>(m_Out);

do
Next();
Expand All @@ -1369,16 +1334,7 @@ namespace ECC {

void HKdf::Generator::Generate(Scalar::Native& out, const Hash::Value& hv) const
{
struct Ikm {
Hash::Value m_Secret;
Hash::Value m_Params;
};

NoLeak<Ikm> ikm;
ikm.V.m_Secret = m_Secret.V;
ikm.V.m_Params = hv;

Rfc5869 gen("beam-Key", beam::Blob(&ikm.V, sizeof(ikm.V)));
Rfc5869 gen("beam-Key", m_Secret.V, hv);
gen >> out;
}

Expand All @@ -1396,12 +1352,12 @@ namespace ECC {
static const char szCtx1[] = "gen";
static const char szCtx2[] = "coF";

Rfc5869 gen1("beam-HKdf", hv);
Rfc5869 gen1("beam-HKdf", beam::Blob(NULL, 0), hv);
Rfc5869 gen2 = gen1;

gen1.m_Context = beam::Blob(szCtx1, sizeof(szCtx1));
gen1.Next();
m_Generator.m_Secret = gen1.m_Out;
m_Generator.m_Secret.V = gen1.m_Out;

gen2.m_Context = beam::Blob(szCtx2, sizeof(szCtx2));
gen2 >> m_kCoFactor;
Expand Down Expand Up @@ -1557,11 +1513,19 @@ namespace ECC {

void Signature::Sign(const Hash::Value& msg, const Scalar::Native& sk)
{
NoLeak<Hash::Value> hvRandom;
GenRandom(hvRandom.V); // add extra randomness to the nonce, so it's derived from both deterministic and random parts
struct Secret {
Hash::Value m_hvRandom;
Scalar m_Sk;
};
NoLeak<Secret> s;

GenRandom(s.V.m_hvRandom); // add extra randomness to the nonce, so it's derived from both deterministic and random parts
s.V.m_Sk = sk;

Rfc5869 gen("Schnorr", beam::Blob(&s, sizeof(s)), msg);

MultiSig msig;
msig.m_Nonce.GenerateNonceNnz(sk, msg, &hvRandom.V);
gen >> msig.m_Nonce;

This comment has been minimized.

Copy link
@daira

daira Feb 8, 2019

Am I correct in thinking that this ends up calling

beam/core/ecc.cpp

Lines 1331 to 1341 in 33930e9

NonceGenerator& NonceGenerator::operator >> (Scalar::Native& sk)
{
static_assert(sizeof(Scalar) == sizeof(m_Okm), "");
const Scalar& s = reinterpret_cast<const Scalar&>(m_Okm);
do
get_Okm();
while (!sk.ImportNnz(s));
return *this;
}
which uses rejection sampling to sample a uniform nonce?

A Schnorr nonce definitely needs to be uniform and unbiased.

msig.m_NoncePub = Context::get().G * msig.m_Nonce;

Scalar::Native k;
Expand Down
2 changes: 0 additions & 2 deletions core/ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ namespace ECC
class Oracle;
struct NonceGenerator;

void GenerateNonce(uintBig&, const uintBig& sk, const uintBig& msg, const uintBig* pMsg2, uint32_t nAttempt /* = 0 */);

struct Scalar
{
static const uintBig s_Order;
Expand Down
13 changes: 3 additions & 10 deletions core/ecc_bulletproof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,18 +591,11 @@ namespace ECC {
}

struct NonceGenerator
:public Rfc5869
{
Oracle m_Oracle;
const uintBig& m_Seed;

NonceGenerator(const uintBig& seed) :m_Seed(seed) {}

void operator >> (Scalar::Native& k)
NonceGenerator(const uintBig& seed)
:Rfc5869("bulletproof", seed, beam::Blob(NULL, 0))
{
NoLeak<Hash::Value> hv;
m_Oracle >> hv.V;

k.GenerateNonceNnz(m_Seed, hv.V, NULL);
}
};

Expand Down
12 changes: 5 additions & 7 deletions core/ecc_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,6 @@ namespace ECC

bool ImportNnz(const Scalar&); // returns true if succeeded: i.e. must not overflow & non-zero. Constant time guaranteed.
void GenRandomNnz();

void GenerateNonceNnz(const uintBig& sk, const uintBig& msg, const uintBig* pMsg2, uint32_t nAttempt = 0);
void GenerateNonceNnz(const Scalar::Native& sk, const uintBig& msg, const uintBig* pMsg2, uint32_t nAttempt = 0);
};

class Point::Native
Expand Down Expand Up @@ -467,18 +464,19 @@ namespace ECC

class Rfc5869
{
NoLeak<Hash::Value> m_Pkr;
Hash::Value m_Pkr;
beam::uintBig_t<1> m_Counter; // wraps-around, it's fine
bool m_bFirstTime;

void Reset(const char* szSalt, uint32_t nSalt, const beam::Blob& ikm);
void Reset(const char* szSalt, uint32_t nSalt, const beam::Blob& secret, const beam::Blob& ikm);

public:
template <uint32_t nSalt>
Rfc5869(const char(&szSalt)[nSalt], const beam::Blob& ikm) { Reset(szSalt, nSalt, ikm); }
Rfc5869(const char(&szSalt)[nSalt], const beam::Blob& secret, const beam::Blob& ikm) { Reset(szSalt, nSalt, secret, ikm); }
~Rfc5869() { SecureErase(*this); }

beam::Blob m_Context;
NoLeak<Hash::Value> m_Out;
Hash::Value m_Out;

void Next();
void operator >> (Scalar::Native&);
Expand Down
2 changes: 1 addition & 1 deletion wallet/unittests/wallet_db_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ void TestTxParameters()
WALLET_CHECK(equal(b.begin(), b.end(), b2.begin(), b2.end()));

ECC::Scalar::Native s, s2;
s.GenerateNonceNnz(uintBig(123U), uintBig(321U), nullptr);
s = 123U;
WALLET_CHECK(wallet::setTxParameter(db, txID, TxParameterID::BlindingExcess, s, false));
WALLET_CHECK(wallet::getTxParameter(db, txID, TxParameterID::BlindingExcess, s2));
WALLET_CHECK(s == s2);
Expand Down

0 comments on commit 6e3217c

Please sign in to comment.