Browse Source

implement ecies mac tag

cl-refactor
subtly 10 years ago
parent
commit
bde85adee7
  1. 2
      libdevcore/vector_ref.h
  2. 43
      libdevcrypto/CryptoPP.cpp
  3. 3
      libdevcrypto/CryptoPP.h

2
libdevcore/vector_ref.h

@ -40,7 +40,7 @@ public:
bool empty() const { return !m_count; }
vector_ref<_T> next() const { return vector_ref<_T>(m_data + m_count, m_count); }
vector_ref<_T> cropped(size_t _begin, size_t _count = ~size_t(0)) const { if (m_data && _begin + std::max(size_t(0), _count) <= m_count) return vector_ref<_T>(m_data + _begin, _count == ~size_t(0) ? m_count - _begin : _count); else return vector_ref<_T>(); }
void retarget(_T const* _d, size_t _s) { m_data = _d; m_count = _s; }
void retarget(_T* _d, size_t _s) { m_data = _d; m_count = _s; }
void retarget(std::vector<_T> const& _t) { m_data = _t.data(); m_count = _t.size(); }
void copyTo(vector_ref<typename std::remove_const<_T>::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); }
void populate(vector_ref<typename std::remove_const<_T>::type> _t) const { copyTo(_t); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); }

43
libdevcrypto/CryptoPP.cpp

@ -34,7 +34,7 @@ static_assert(dev::Signature::size == 65, "Signature must be 65 bytes.");
bytes Secp256k1::eciesKDF(Secret _z, bytes _s1, unsigned kdBitLen)
{
// similar to go ecies implementation
// interop w/go ecies implementation
if (!_s1.size())
{
@ -76,9 +76,7 @@ bytes Secp256k1::eciesKDF(Secret _z, bytes _s1, unsigned kdBitLen)
void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher)
{
// similar to go ecies implementation
// todo: s1/s2/tag
// interop w/go ecies implementation
auto r = KeyPair::create();
h256 z;
ecdh::agree(r.sec(), _k, z);
@ -91,38 +89,34 @@ void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher)
encryptSymNoAuth(*(Secret*)eKey.data(), bytesConstRef(&io_cipher), cipherText, h128());
if (!cipherText.size())
return;
// d := messageTag(params.Hash, Km, em, s2)
// copy(ct[len(Rb)+len(em):], d)
bytes msg(1 + Public::size + cipherText.size() + 32);
msg[0] = 0x04;
r.pub().ref().copyTo(bytesRef(&msg).cropped(1, Public::size));
bytesRef msgCipherRef = bytesRef(&msg).cropped(1 + Public::size, cipherText.size());
bytesConstRef(&cipherText).copyTo(msgCipherRef);
// tag message
CryptoPP::HMAC<SHA256> ctx(mKey.data(), mKey.size());
ctx.Update(cipherText.data(), cipherText.size());
ctx.Final(msg.data() + 1 + Public::size + cipherText.size());
io_cipher.resize(msg.size());
io_cipher.swap(msg);
}
void eciesMessageTag()
bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text)
{
// interop w/go ecies implementation
}
void Secp256k1::decryptECIES(Secret const& _k, bytes& io_text)
{
// similar to go ecies implementation
// todo: s1/s2
// io_cipher[0] must be 2, 3, or 4, else invalidpublickey
if (io_text[0] < 2 || io_text[0] > 4)
// invalid message: publickey
return;
return false;
if (io_text.size() < (1 + Public::size + h256::size + 1))
// invalid message: length
return;
return false;
h256 z;
ecdh::agree(_k, *(Public*)(io_text.data()+1), z);
@ -134,9 +128,22 @@ void Secp256k1::decryptECIES(Secret const& _k, bytes& io_text)
bytes plain;
size_t cipherLen = io_text.size() - 1 - Public::size - h256::size;
bytesConstRef cipher(io_text.data() + 1 + Public::size, cipherLen);
bytesConstRef msgMac(cipher.data() + cipher.size(), h256::size);
// verify tag
CryptoPP::HMAC<SHA256> ctx(mKey.data(), mKey.size());
ctx.Update(cipher.data(), cipher.size());
h256 mac;
ctx.Final(mac.data());
for (unsigned i = 0; i < h256::size; i++)
if (mac[i] != msgMac[i])
return false;
decryptSymNoAuth(*(Secret*)eKey.data(), h128(), cipher, plain);
io_text.resize(plain.size());
io_text.swap(plain);
return true;
}
void Secp256k1::encrypt(Public const& _k, bytes& io_cipher)

3
libdevcrypto/CryptoPP.h

@ -65,6 +65,7 @@ inline Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.
/**
* CryptoPP secp256k1 algorithms.
* @todo Collect ECIES methods into class.
*/
class Secp256k1
{
@ -85,7 +86,7 @@ public:
void encryptECIES(Public const& _k, bytes& io_cipher);
/// Temporary; to replace decrypt once interop w/go is passing.
void decryptECIES(Secret const& _k, bytes& io_text);
bool decryptECIES(Secret const& _k, bytes& io_text);
/// Key derivation function used by ECIES.
bytes eciesKDF(Secret _z, bytes _s1, unsigned kdBitLen = 256);

Loading…
Cancel
Save