예제 #1
0
void Secp256k1PP::agree(Secret const& _s, Public const& _r, Secret& o_s)
{
	// TODO: mutex ASN1::secp256k1() singleton
	// Creating Domain is non-const for m_oid and m_oid is not thread-safe
	ECDH<ECP>::Domain d(ASN1::secp256k1());
	assert(d.AgreedValueLength() == sizeof(o_s));
	byte remote[65] = {0x04};
	memcpy(&remote[1], _r.data(), 64);
	d.Agree(o_s.writable().data(), _s.data(), remote);
}
예제 #2
0
void Secp256k1PP::exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& o_p)
{
	bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
	
	{
		Guard l(x_params);
		m_params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
		assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
	}

	memcpy(o_p.data(), &prefixedKey[1], Public::size);
}
예제 #3
0
void ECDHEKeyExchange::exchange(bytes& o_exchange)
{
	if (!m_ephemeralSecret)
		// didn't agree on public remote
		BOOST_THROW_EXCEPTION(InvalidState());

	// The key exchange payload is in two parts and is encrypted
	// using ephemeral keypair.
	//
	// The first part is the 'prefix' which is a zero-knowledge proof
	// allowing the remote to resume or emplace a previous session.
	// If a session previously exists:
	//	prefix is sha3(token) // todo: ephemeral entropy from both sides
	// If a session doesn't exist:
	//	prefix is sha3(m_ephemeralSecret)
	//
	// The second part is encrypted using the public key which relates to the prefix.
	
	Public encpk = m_known.first ? m_known.first : m_remoteEphemeral;
	bytes exchange(encpk.asBytes());
	
	// This is the public key which we would like the remote to use,
	// which maybe different than the previously-known public key.
	//
	// Here we should pick an appropriate alias or generate a new one,
	// but for now, we use static alias passed to constructor.
	//
	Public p = toPublic(m_alias.m_secret);
	exchange.resize(exchange.size() + sizeof(p));
	memcpy(&exchange[exchange.size() - sizeof(p)], p.data(), sizeof(p));
	
	// protocol parameters; should be fixed size
	bytes v(1, 0x80);
	exchange.resize(exchange.size() + v.size());
	memcpy(&exchange[exchange.size() - v.size()], v.data(), v.size());
	
	h256 auth;
	sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref());
	Signature sig = s_secp256k1.sign(m_alias.m_secret, auth);
	exchange.resize(exchange.size() + sizeof(sig));
	memcpy(&exchange[exchange.size() - sizeof(sig)], sig.data(), sizeof(sig));
	
	aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0);
	h256 prefix(sha3(m_known.second ? m_known.second : (h256)m_remoteEphemeral));
	aes.update(prefix.ref());
	
	s_secp256k1.encrypt(encpk, exchange);
	aes.update(&exchange);

	aes.streamOut(o_exchange);
}
예제 #4
0
Public Secp256k1PP::recover(Signature _signature, bytesConstRef _message)
{
	Public recovered;
	
	Integer r(_signature.data(), 32);
	Integer s(_signature.data()+32, 32);
	// cryptopp encodes sign of y as 0x02/0x03 instead of 0/1 or 27/28
	byte encodedpoint[33];
	encodedpoint[0] = _signature[64] | 2;
	memcpy(&encodedpoint[1], _signature.data(), 32);
	
	ECP::Element x;
	{
		m_curve.DecodePoint(x, encodedpoint, 33);
		if (!m_curve.VerifyPoint(x))
			return recovered;
	}
	
//	if (_signature[64] & 2)
//	{
//		r += m_q;
//		Guard l(x_params);
//		if (r >= m_params.GetMaxExponent())
//			return recovered;
//	}
	
	Integer z(_message.data(), 32);
	Integer rn = r.InverseMod(m_q);
	Integer u1 = m_q - (rn.Times(z)).Modulo(m_q);
	Integer u2 = (rn.Times(s)).Modulo(m_q);
	
	ECP::Point p;
	byte recoveredbytes[65];
	{
		// todo: make generator member
		p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator());
		if (p.identity)
			return Public();
		m_curve.EncodePoint(recoveredbytes, p, false);
	}
	memcpy(recovered.data(), &recoveredbytes[1], 64);
	return recovered;
}