CryptoPP::ECP::Point Sum (const CryptoPP::ECP::Point& p1, const CryptoPP::ECP::Point& p2) const { CryptoPP::Integer m = d*p1.x*p2.x*p1.y*p2.y, x = a_times_b_mod_c (p1.x*p2.y + p2.x*p1.y, (CryptoPP::Integer::One() + m).InverseMod (q), q), y = a_times_b_mod_c (p1.y*p2.y + p1.x*p2.x, (CryptoPP::Integer::One() - m).InverseMod (q), q); return CryptoPP::ECP::Point {x, y}; }
bool verify(CryptoPP::ECPPoint Q, byte *message, unsigned message_length, CryptoPP::Integer r, CryptoPP::Integer s){ auto ec = common::ec_parameters().GetCurve(); auto G = common::ec_parameters().GetSubgroupGenerator(); auto n = common::ec_parameters().GetGroupOrder(); Integer z = hash_m_to_int(message, message_length, n.ByteCount()); // verify if (Q == ec.Identity()){ cerr << "Q == O" << endl; return false; } if (!(ec.Multiply(n, Q) == ec.Identity())){ cerr << "n x Q != O" << endl; return false; } if (r <= 0 || r >= n){ cerr << "incorrect r" << endl; return false; } if (s <= 0 || s >= n){ cerr << "incorrect s" << endl; return false; } Integer w = s.InverseMod(n); Integer u1 = a_times_b_mod_c(z, w, n); Integer u2 = a_times_b_mod_c(r, w, n); ECPPoint P2 = ec.Add(ec.Multiply(u1, G), ec.Multiply(u2, Q)); if (P2.x != r){ cerr << "P2.x != r" << endl; return false; } return true; }
void B::cont_sig(ECPPoint Ks, Integer cs, byte *m, unsigned m_len){ kb.Randomize(common::rng(), Integer::One(), n-1); K = ec.Multiply(kb, Ks); r = K.x % n; if (r == 0) throw ProtocolException("r == 0"); Integer hi = hash_m_to_int(m, m_len, n.ByteCount()); Integer c1 = paillier.enc( a_times_b_mod_c(kb.InverseMod(n), hi, n) ); Integer t = a_times_b_mod_c(a_times_b_mod_c(kb.InverseMod(n), r, n), db, n); Integer c2 = a_times_b_mod_c(c1, a_exp_b_mod_c(cs, t, paillier.get_n2()), paillier.get_n2()); Integer u(common::rng(), Integer::Zero(), n*n - 1); cb = a_times_b_mod_c(c2, paillier.enc(u*n), paillier.get_n2()); }
vI Commiter::zk_4(const vI &commit_values) { if (commit_values.size() != com.K+1) { throw ProtocolException("invalid commit_values size"); } for(unsigned i = 1; i <= com.K; ++i) { if (!regular_verify(commits[i], commit_values[i])) { throw ProtocolException("regular commit didn't verify"); } } vI y(com.K+1); for(unsigned i = 1; i <= com.K; ++i) { Integer yi = a_times_b_mod_c( commit_values[i], a_exp_b_mod_c(2, Integer::Power2(i-1), order), order); yi += alpha[i]; yi %= order; y[i] = yi; } return y; }
CryptoPP::Integer RecoverX (const CryptoPP::Integer& y) const { auto y2 = y.Squared (); auto xx = (y2 - CryptoPP::Integer::One())*(d*y2 + CryptoPP::Integer::One()).InverseMod (q); auto x = a_exp_b_mod_c (xx, (q + CryptoPP::Integer (3)).DividedBy (8), q); if (!(x.Squared () - xx).Modulo (q).IsZero ()) x = a_times_b_mod_c (x, I, q); if (x.IsOdd ()) x = q - x; return x; }
vector<bool> Receiver::decode(Integer v) { vector<bool> res(com.l); for(unsigned i = 0; i < com.l; ++i) { res[i] = com.S[i] ^ v.GetBit(0); v = a_times_b_mod_c(v, v, com.n); } if (v != com.u) { throw SanityException("v != com.u"); } return res; }
void Receiver::zk_5(const vI &y) { if (y.size() != com.K+1) { throw ProtocolException("y size != K+1"); } for(unsigned i = 1; i <= com.K; ++i) { Integer zi = a_times_b_mod_c( a_exp_b_mod_c(com.g, y[i], com.n), a_exp_b_mod_c(com.W[i-1].InverseMod(com.n), commit_values[i], com.n), com.n); if (zi != zw.first[i]) { throw ProtocolException("zi verification failed"); } Integer wi = a_times_b_mod_c( a_exp_b_mod_c(com.W[i-1], y[i], com.n), a_exp_b_mod_c(com.W[i].InverseMod(com.n), commit_values[i], com.n), com.n); if (wi != zw.second[i]) { throw ProtocolException("wi verification failed"); } } }
Commitment Commiter::commit(const unsigned K, const vector<bool> &m) { unsigned available_primes; Integer g, h; Integer a0, a, u; vector<bool> S; vector<Integer> W; unsigned l; // sanity check on m for(bool b: m) { if (b != 0 && b != 1) { throw SanityException("not binary m"); } } l = m.size(); h = Integer(common::rng(), 2, n-1); g = get_g(n, h); order = find_order(p, q, g); a0 = a_exp_b_mod_c(2, Integer::Power2(K) - l, phi); a = a_exp_b_mod_c(2, Integer::Power2(K), phi); u = a_exp_b_mod_c(g, a0, n); S.resize(l); for(unsigned i = 0; i < l; ++i) { S[i] = m[i] ^ u.GetBit(0); u = a_times_b_mod_c(u, u, n); } // sanity check on u if (u != a_exp_b_mod_c(g, a, n)) { throw SanityException("u != g ** a"); } W.resize(K+1); for(unsigned i = 0; i <= K; ++i) { Integer exp = a_exp_b_mod_c(2, Integer::Power2(i) , phi); W[i] = a_exp_b_mod_c(g, exp, n); } // sanity check on W if (W[0] != (g*g % n) || W[1] != (g*g*g*g % n) || W[K] != u) { throw SanityException("invalid W"); } com = Commitment(K, n, h, g, u, S, W, m.size()); return com; }
vector<bool> Receiver::force_open_smart() { Integer v = com.W[com.K-1]; for(Integer i = 0; i < Integer::Power2(com.K-1) - com.l; ++i) { v = a_times_b_mod_c(v, v, com.n); } Integer u = a_exp_b_mod_c(v, Integer::Power2(com.l), com.n); if (u != com.u) { throw ProtocolException("u != com.u"); } return decode(v); }
BinaryData CryptoECDSA::ECMultiplyScalars(BinaryData const & A, BinaryData const & B) { // Hardcode the order of the secp256k1 EC group static BinaryData N = BinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); CryptoPP::Integer intA, intB, intC, intN; intA.Decode(A.getPtr(), A.getSize(), UNSIGNED); intB.Decode(B.getPtr(), B.getSize(), UNSIGNED); intN.Decode(N.getPtr(), N.getSize(), UNSIGNED); intC = a_times_b_mod_c(intA, intB, intN); BinaryData C(32); intC.Encode(C.getPtr(), 32, UNSIGNED); return C; }
void S::finish_sig(Integer r, Integer cb){ this->r = r; Integer s2 = paillier.dec(cb) % n; s = a_times_b_mod_c(ks.InverseMod(n), s2, n); if (s == 0){ throw ProtocolException("ERR s==0 restart protocol"); } if (s > n - s) { s = n - s; } // bool result = verifier.VerifyMessage(get_data(), get_data_length(), signature, 64); bool result = verify(Q, get_data(), get_data_length(), r, s); if (!result){ throw ProtocolException("Invalid signature generated!"); } else { } }
///////////////////////////////////////////////////////////////////////////// // Deterministically generate new private key using a chaincode // Changed: added using the hash of the public key to the mix // b/c multiplying by the chaincode alone is too "linear" // (there's no reason to believe it's insecure, but it doesn't // hurt to add some extra entropy/non-linearity to the chain // generation process) SecureBinaryData CryptoECDSA::ComputeChainedPrivateKey( SecureBinaryData const & binPrivKey, SecureBinaryData const & chainCode, SecureBinaryData binPubKey, SecureBinaryData* multiplierOut) { if(CRYPTO_DEBUG) { cout << "ComputeChainedPrivateKey:" << endl; cout << " BinPrv: " << binPrivKey.toHexStr() << endl; cout << " BinChn: " << chainCode.toHexStr() << endl; cout << " BinPub: " << binPubKey.toHexStr() << endl; } if( binPubKey.getSize()==0 ) binPubKey = ComputePublicKey(binPrivKey); if( binPrivKey.getSize() != 32 || chainCode.getSize() != 32) { LOGERR << "***ERROR: Invalid private key or chaincode (both must be 32B)"; LOGERR << "BinPrivKey: " << binPrivKey.getSize(); LOGERR << "BinPrivKey: (not logged for security)"; //LOGERR << "BinPrivKey: " << binPrivKey.toHexStr(); LOGERR << "BinChain : " << chainCode.getSize(); LOGERR << "BinChain : " << chainCode.toHexStr(); } // Adding extra entropy to chaincode by xor'ing with hash256 of pubkey BinaryData chainMod = binPubKey.getHash256(); BinaryData chainOrig = chainCode.getRawCopy(); BinaryData chainXor(32); for(uint8_t i=0; i<8; i++) { uint8_t offset = 4*i; *(uint32_t*)(chainXor.getPtr()+offset) = *(uint32_t*)( chainMod.getPtr()+offset) ^ *(uint32_t*)(chainOrig.getPtr()+offset); } // Hard-code the order of the group static SecureBinaryData SECP256K1_ORDER_BE = SecureBinaryData().CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); CryptoPP::Integer mult, origPrivExp, ecOrder; // A mult.Decode(chainXor.getPtr(), chainXor.getSize(), UNSIGNED); // B origPrivExp.Decode(binPrivKey.getPtr(), binPrivKey.getSize(), UNSIGNED); // C ecOrder.Decode(SECP256K1_ORDER_BE.getPtr(), SECP256K1_ORDER_BE.getSize(), UNSIGNED); // A*B mod C will get us a new private key exponent CryptoPP::Integer newPrivExponent = a_times_b_mod_c(mult, origPrivExp, ecOrder); // Convert new private exponent to big-endian binary string SecureBinaryData newPrivData(32); newPrivExponent.Encode(newPrivData.getPtr(), newPrivData.getSize(), UNSIGNED); if(multiplierOut != NULL) (*multiplierOut) = SecureBinaryData(chainXor); //LOGINFO << "Computed new chained private key using:"; //LOGINFO << " Public key: " << binPubKey.toHexStr().c_str(); //LOGINFO << " PubKeyHash: " << chainMod.toHexStr().c_str(); //LOGINFO << " Chaincode: " << chainOrig.toHexStr().c_str(); //LOGINFO << " Multiplier: " << chainXor.toHexStr().c_str(); return newPrivData; }
virtual IIntegerImpl *Multiply(const IIntegerImpl * const multiplicand, const IIntegerImpl * const modulus) const { return new CppIntegerImpl(a_times_b_mod_c(m_data, GetData(multiplicand), GetData(modulus))); }