Browse Source

initial handshake on the wire

cl-refactor
subtly 10 years ago
parent
commit
4814303c09
  1. 62
      libdevcrypto/Common.cpp
  2. 4
      libdevcrypto/Common.h
  3. 2
      libdevcrypto/CryptoPP.cpp
  4. 5
      libdevcrypto/ECDHE.cpp
  5. 9
      libdevcrypto/ECDHE.h
  6. 235
      libp2p/Host.cpp
  7. 47
      libp2p/Host.h
  8. 66
      test/crypto.cpp

62
libdevcrypto/Common.cpp

@ -92,6 +92,68 @@ bool dev::decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plain)
return decrypt(_k, _cipher, o_plain);
}
h256 dev::encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher)
{
auto iv = Nonce::get();
return encryptSymNoAuth(_k, _plain, o_cipher, iv);
}
h256 dev::encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher, h256 const& _iv)
{
const int c_aesBlockLen = 16;
o_cipher.resize(_plain.size() + (c_aesBlockLen - (_plain.size() % c_aesBlockLen)) % c_aesBlockLen);
bytes underflowBytes(0);
auto size = _plain.size() - (_plain.size() % c_aesBlockLen);
if (o_cipher.size() > _plain.size())
{
underflowBytes.resize(c_aesBlockLen);
_plain.cropped(size, _plain.size() - size).copyTo(&underflowBytes);
}
const int c_aesKeyLen = 32;
SecByteBlock key(_k.data(), c_aesKeyLen);
try
{
CTR_Mode<AES>::Encryption e;
e.SetKeyWithIV(key, key.size(), _iv.data());
if (size)
e.ProcessData(o_cipher.data(), _plain.data(), _plain.size());
if (underflowBytes.size())
e.ProcessData(o_cipher.data(), underflowBytes.data(), underflowBytes.size());
return _iv;
}
catch(CryptoPP::Exception& e)
{
cerr << e.what() << endl;
o_cipher.resize(0);
return h256();
}
}
bool dev::decryptSymNoAuth(Secret const& _k, h256 const& _iv, bytesConstRef _cipher, bytes& o_plaintext)
{
const int c_aesKeyLen = 32;
const int c_aesBlockLen = 16;
asserts(_cipher.size() % c_aesBlockLen == 0);
o_plaintext.resize(_cipher.size());
SecByteBlock key(_k.data(), c_aesKeyLen);
try
{
CTR_Mode<AES>::Decryption d;
d.SetKeyWithIV(key, key.size(), _iv.data());
d.ProcessData(o_plaintext.data(), _cipher.data(), _cipher.size());
return true;
}
catch(CryptoPP::Exception& e)
{
cerr << e.what() << endl;
o_plaintext.resize(0);
return false;
}
}
Public dev::recover(Signature const& _sig, h256 const& _message)
{
return s_secp256k1.recover(_sig, _message.ref());

4
libdevcrypto/Common.h

@ -93,6 +93,10 @@ void encryptSym(Secret const& _k, bytesConstRef _plain, bytes& o_cipher);
/// Symmetric decryption.
bool decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
h256 encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher);
h256 encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher, h256 const& _iv);
bool decryptSymNoAuth(Secret const& _k, h256 const& _iv, bytesConstRef _cipher, bytes& o_plaintext);
/// Recovers Public key from signed message hash.
Public recover(Signature const& _sig, h256 const& _hash);

2
libdevcrypto/CryptoPP.cpp

@ -201,7 +201,7 @@ void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s)
{
(void)o_s;
(void)_s;
ECDH<ECP>::Domain d(m_oid);
ECDH<ECP>::Domain d(ASN1::secp256k1());
assert(d.AgreedValueLength() == sizeof(o_s));
byte remote[65] = {0x04};
memcpy(&remote[1], _r.data(), 64);

5
libdevcrypto/ECDHE.cpp

@ -29,6 +29,11 @@ using namespace dev::crypto;
static Secp256k1 s_secp256k1;
void dev::crypto::ecdh::agree(Secret const& _s, Public const& _r, h256& o_s)
{
s_secp256k1.agree(_s, _r, o_s);
}
void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret)
{
if (m_remoteEphemeral)

9
libdevcrypto/ECDHE.h

@ -49,6 +49,11 @@ private:
Secret m_secret;
};
namespace ecdh
{
void agree(Secret const& _s, Public const& _r, h256& o_s);
}
/**
* @brief Derive DH shared secret from EC keypairs.
* As ephemeral keys are single-use, agreement is limited to a single occurence.
@ -82,10 +87,10 @@ class ECDHEKeyExchange: private ECDHE
{
public:
/// Exchange with unknown remote (pass public key for ingress exchange)
ECDHEKeyExchange(Alias& _k): m_alias(_k) {};
ECDHEKeyExchange(Alias& _k): m_alias(_k) {}
/// Exchange with known remote
ECDHEKeyExchange(Alias& _k, AliasSession _known): m_alias(_k), m_known(_known) {};
ECDHEKeyExchange(Alias& _k, AliasSession _known): m_alias(_k), m_known(_known) {}
/// Provide public key for dh agreement to generate shared secret.
void agree(Public const& _remoteEphemeral);

235
libp2p/Host.cpp

@ -337,7 +337,7 @@ void Host::runAcceptor()
{
// doHandshake takes ownersihp of *s via std::move
// incoming connection; we don't yet know nodeid
doHandshake(s, NodeId());
doHandshake(new Handshake(s));
success = true;
}
catch (Exception const& _e)
@ -351,15 +351,18 @@ void Host::runAcceptor()
}
// asio doesn't close socket on error
if (!success && s->is_open())
if (!success)
{
boost::system::error_code ec;
s->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
s->close();
if (s->is_open())
{
boost::system::error_code ec;
s->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
s->close();
}
delete s;
}
m_accepting = false;
delete s;
if (ec.value() < 1)
runAcceptor();
@ -367,22 +370,209 @@ void Host::runAcceptor()
}
}
void Host::doHandshake(bi::tcp::socket* _socket, NodeId _nodeId)
void Host::doHandshake(Handshake* _h, boost::system::error_code _ech)
{
try {
clog(NetConnect) << "Accepting connection for " << _socket->remote_endpoint();
} catch (...){}
if (_ech)
{
boost::system::error_code ec;
_h->socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
if (_h->socket->is_open())
_h->socket->close();
delete _h;
return;
}
if (!_h->started())
{
clog(NetConnect) << "Authenticating connection for " << _h->socket->remote_endpoint();
if (_h->originated)
{
clog(NetConnect) << "devp2p.connect.egress sending auth";
// egress: tx auth
asserts(_h->remote);
_h->auth.resize(Signature::size + h256::size + Public::size + h256::size + 1);
bytesConstRef sig(&_h->auth[0], Signature::size);
bytesConstRef hepubk(&_h->auth[Signature::size], h256::size);
bytesConstRef pubk(&_h->auth[Signature::size + h256::size], Public::size);
bytesConstRef nonce(&_h->auth[Signature::size + h256::size + Public::size], h256::size);
// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
crypto::ecdh::agree(m_alias.sec(), _h->remote, _h->ss);
sign(_h->ecdhe.seckey(), _h->ss ^ _h->nonce).ref().copyTo(sig);
sha3(_h->ecdhe.pubkey().ref(), hepubk);
m_alias.pub().ref().copyTo(pubk);
_h->nonce.ref().copyTo(nonce);
_h->auth[_h->auth.size() - 1] = 0x0;
encrypt(_h->remote, &_h->auth, _h->authCipher);
ba::async_write(*_h->socket, ba::buffer(_h->authCipher), [=](boost::system::error_code ec, std::size_t)
{
doHandshake(_h, ec);
});
}
else
{
clog(NetConnect) << "devp2p.connect.ingress recving auth";
// ingress: rx auth
_h->authCipher.resize(279);
ba::async_read(*_h->socket, ba::buffer(_h->authCipher, 279), [=](boost::system::error_code ec, std::size_t)
{
if (ec)
doHandshake(_h, ec);
else
{
decrypt(m_alias.sec(), bytesConstRef(&_h->authCipher), _h->auth);
bytesConstRef sig(&_h->auth[0], Signature::size);
bytesConstRef hepubk(&_h->auth[Signature::size], h256::size);
bytesConstRef pubk(&_h->auth[Signature::size + h256::size], Public::size);
bytesConstRef nonce(&_h->auth[Signature::size + h256::size + Public::size], h256::size);
pubk.copyTo(_h->remote.ref());
nonce.copyTo(_h->remoteNonce.ref());
crypto::ecdh::agree(m_alias.sec(), _h->remote, _h->ss);
_h->remoteEphemeral = recover(*(Signature*)sig.data(), _h->ss ^ _h->remoteNonce);
assert(sha3(_h->remoteEphemeral) == *(h256*)hepubk.data());
doHandshake(_h);
}
});
}
}
else if (_h->started() && !_h->acked())
if (_h->originated)
{
clog(NetConnect) << "devp2p.connect.egress recving ack";
// egress: rx ack
_h->ackCipher.resize(182);
ba::async_read(*_h->socket, ba::buffer(_h->ackCipher, 182), [=](boost::system::error_code ec, std::size_t)
{
if (ec)
doHandshake(_h, ec);
else
{
decrypt(m_alias.sec(), bytesConstRef(&_h->ackCipher), _h->ack);
bytesConstRef(&_h->ack).cropped(0, Public::size).copyTo(_h->remoteEphemeral.ref());
bytesConstRef(&_h->ack).cropped(Public::size, h256::size).copyTo(_h->remoteNonce.ref());
doHandshake(_h);
}
});
}
else
{
clog(NetConnect) << "devp2p.connect.ingress sending ack";
// ingress: tx ack
_h->ack.resize(Public::size + h256::size + 1);
bytesConstRef epubk(&_h->ack[0], Public::size);
bytesConstRef nonce(&_h->ack[Public::size], h256::size);
_h->ecdhe.pubkey().ref().copyTo(epubk);
_h->nonce.ref().copyTo(nonce);
_h->ack[_h->ack.size() - 1] = 0x0;
encrypt(_h->remote, &_h->ack, _h->ackCipher);
ba::async_write(*_h->socket, ba::buffer(_h->ackCipher), [=](boost::system::error_code ec, std::size_t)
{
doHandshake(_h, ec);
});
}
else if (_h->started() && _h->acked())
{
if (_h->originated)
clog(NetConnect) << "devp2p.connect.egress sending magic sequence";
else
clog(NetConnect) << "devp2p.connect.ingress sending magic sequence";
PeerSecrets* k = new PeerSecrets;
bytes keyMaterialBytes(512);
bytesConstRef keyMaterial(&keyMaterialBytes);
_h->ecdhe.agree(_h->remoteEphemeral, _h->ess);
_h->ess.ref().copyTo(keyMaterial.cropped(0, h256::size));
_h->ss.ref().copyTo(keyMaterial.cropped(h256::size, h256::size));
// auto token = sha3(ssA);
k->encryptK = sha3(keyMaterial);
k->encryptK.ref().copyTo(keyMaterial.cropped(h256::size, h256::size));
k->macK = sha3(keyMaterial);
// Initiator egress-mac: sha3(mac-secret^recipient-nonce || auth-sent-init)
// ingress-mac: sha3(mac-secret^initiator-nonce || auth-recvd-ack)
// Recipient egress-mac: sha3(mac-secret^initiator-nonce || auth-sent-ack)
// ingress-mac: sha3(mac-secret^recipient-nonce || auth-recvd-init)
bytes const& egressCipher = _h->originated ? _h->authCipher : _h->ackCipher;
keyMaterialBytes.resize(h256::size + egressCipher.size());
keyMaterial.retarget(keyMaterialBytes.data(), keyMaterialBytes.size());
(k->macK ^ _h->remoteNonce).ref().copyTo(keyMaterial);
bytesConstRef(&egressCipher).copyTo(keyMaterial.cropped(h256::size, egressCipher.size()));
k->egressMac = sha3(keyMaterial);
bytes const& ingressCipher = _h->originated ? _h->ackCipher : _h->authCipher;
keyMaterialBytes.resize(h256::size + ingressCipher.size());
keyMaterial.retarget(keyMaterialBytes.data(), keyMaterialBytes.size());
(k->macK ^ _h->nonce).ref().copyTo(keyMaterial);
bytesConstRef(&ingressCipher).copyTo(keyMaterial.cropped(h256::size, ingressCipher.size()));
k->ingressMac = sha3(keyMaterial);
// TESTING: send encrypt magic sequence
bytes magic {0x22,0x40,0x08,0x91};
encryptSymNoAuth(k->encryptK, &magic, k->magicCipherAndMac, h256());
k->magicCipherAndMac.resize(k->magicCipherAndMac.size() + 32);
sha3mac(k->egressMac.ref(), &magic, k->egressMac.ref());
k->egressMac.ref().copyTo(bytesConstRef(&k->magicCipherAndMac).cropped(k->magicCipherAndMac.size() - 32, 32));
clog(NetConnect) << "devp2p.connect.egress txrx magic sequence";
ba::async_write(*_h->socket, ba::buffer(k->magicCipherAndMac), [this, k, _h, magic](boost::system::error_code ec, std::size_t)
{
if (ec)
{
delete k;
doHandshake(_h, ec);
return;
}
ba::async_read(*_h->socket, ba::buffer(k->recvdMagicCipherAndMac, k->magicCipherAndMac.size()), [this, k, _h, magic](boost::system::error_code ec, std::size_t)
{
if (_h->originated)
clog(NetNote) << "devp2p.connect.egress recving magic sequence";
else
clog(NetNote) << "devp2p.connect.ingress recving magic sequence";
shared_ptr<Peer> p;
if (_nodeId)
p = m_peers[_nodeId];
if (ec)
{
delete k;
doHandshake(_h, ec);
return;
}
if (!p)
p.reset(new Peer());
p->endpoint.tcp.address(_socket->remote_endpoint().address());
bytes decryptedMagic;
decryptSymNoAuth(k->encryptK, h256(), &k->recvdMagicCipherAndMac, decryptedMagic);
clog(NetNote) << "devp2p.connect received magic sequence";
auto ps = std::make_shared<Session>(this, std::move(*_socket), p);
ps->start();
shared_ptr<Peer> p;
p = m_peers[_h->remote];
if (!p)
{
p.reset(new Peer());
p->id = _h->remote;
}
p->endpoint.tcp.address(_h->socket->remote_endpoint().address());
p->m_lastDisconnect = NoDisconnect;
p->m_lastConnected = std::chrono::system_clock::now();
p->m_failedAttempts = 0;
auto ps = std::make_shared<Session>(this, move(*_h->socket), p);
ps->start();
delete k;
});
});
}
else
{
clog(NetConnect) << "Disconnecting " << _h->socket->remote_endpoint() << " (Authentication Failed)";
boost::system::error_code ec;
_h->socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
_h->socket->close();
delete _h;
}
}
string Host::pocHost()
@ -467,18 +657,13 @@ void Host::connect(std::shared_ptr<Peer> const& _p)
clog(NetConnect) << "Connection refused to node" << _p->id.abridged() << "@" << _p->peerEndpoint() << "(" << ec.message() << ")";
_p->m_lastDisconnect = TCPError;
_p->m_lastAttempted = std::chrono::system_clock::now();
delete s;
}
else
{
clog(NetConnect) << "Connected to" << _p->id.abridged() << "@" << _p->peerEndpoint();
_p->m_lastDisconnect = NoDisconnect;
_p->m_lastConnected = std::chrono::system_clock::now();
_p->m_failedAttempts = 0;
auto ps = make_shared<Session>(this, std::move(*s), _p);
ps->start();
doHandshake(new Handshake(s, _p->id));
}
delete s;
Guard l(x_pendingNodeConns);
m_pendingPeerConns.erase(nptr);
});

47
libp2p/Host.h

@ -34,6 +34,7 @@
#include <libdevcore/Worker.h>
#include <libdevcore/RangeMask.h>
#include <libdevcrypto/Common.h>
#include <libdevcrypto/ECDHE.h>
#include "NodeTable.h"
#include "HostCapability.h"
#include "Network.h"
@ -157,6 +158,48 @@ protected:
void restoreNetwork(bytesConstRef _b);
private:
struct Handshake
{
/// Handshake for ingress connection. Takes ownership of socket.
Handshake(bi::tcp::socket* _socket): socket(std::move(_socket)), originated(false) { crypto::Nonce::get().ref().copyTo(nonce.ref()); }
/// Handshake for egress connection to _remote. Takes ownership of socket.
Handshake(bi::tcp::socket* _socket, NodeId _remote): socket(std::move(_socket)), originated(true), remote(_remote) { crypto::Nonce::get().ref().copyTo(nonce.ref()); }
~Handshake() { delete socket; }
bool started() { return auth.size() > 0; }
bool acked() { return ack.size() > 0; }
/// If originated this is accepting (ingress) node id, otherwise it is originating (egress) node.
NodeId remote;
bi::tcp::socket *socket;
bool originated = false;
bytes auth;
bytes authCipher;
bytes ack;
bytes ackCipher;
Secret ss;
Secret ess;
crypto::ECDHE ecdhe;
h256 nonce;
Public remoteEphemeral;
h256 remoteNonce;
};
struct PeerSecrets
{
Secret encryptK;
Secret macK;
h256 egressMac;
h256 ingressMac;
bytes magicCipherAndMac;
bytes recvdMagicCipherAndMac;
};
/// Populate m_peerAddresses with available public addresses.
void determinePublic(std::string const& _publicAddress, bool _upnp);
@ -171,8 +214,8 @@ private:
/// Called only from startedWorking().
void runAcceptor();
/// Handler for verifying handshake siganture before creating session. _nodeId is passed for outbound connections. If successful, socket is moved to Session via std::move.
void doHandshake(bi::tcp::socket* _socket, NodeId _nodeId = NodeId());
/// Attempt to authenticate peer and establish a new session.
void doHandshake(Handshake* _h, boost::system::error_code _ec = boost::system::error_code());
void seal(bytes& _b);

66
test/crypto.cpp

@ -321,13 +321,16 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
// authInitiator -> E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
// authRecipient -> E(remote-pubk, ecdhe-random-pubk || nonce || 0x0)
Secret nodeAsecret(sha3("privacy"));
h256 base(sha3("privacy"));
sha3(base.ref(), base.ref());
Secret nodeAsecret(base);
KeyPair nodeA(nodeAsecret);
BOOST_REQUIRE(nodeA.pub());
Secret nodeBsecret(sha3("privacy++"));
sha3(base.ref(), base.ref());
Secret nodeBsecret(base);
KeyPair nodeB(nodeBsecret);
BOOST_REQUIRE(nodeA.pub());
BOOST_REQUIRE(nodeB.pub());
BOOST_REQUIRE_NE(nodeA.sec(), nodeB.sec());
@ -343,7 +346,7 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
bytesConstRef pubk(&auth[Signature::size + h256::size], Public::size);
bytesConstRef nonce(&auth[Signature::size + h256::size + Public::size], h256::size);
s_secp256k1.agree(nodeA.sec(), nodeB.pub(), ssA);
crypto::ecdh::agree(nodeA.sec(), nodeB.pub(), ssA);
sign(eA.seckey(), ssA ^ nonceA).ref().copyTo(sig);
sha3(eA.pubkey().ref(), hepubk);
nodeA.pub().ref().copyTo(pubk);
@ -352,7 +355,7 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
}
bytes authcipher;
encrypt(nodeB.pub(), &auth, authcipher);
BOOST_REQUIRE(authcipher.size());
BOOST_REQUIRE_EQUAL(authcipher.size(), 279);
// Receipient is Bob (nodeB)
ECDHE eB;
@ -360,6 +363,14 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
h256 nonceB(sha3(nAbytes));
bytes ack(Public::size + h256::size + 1);
{
// todo: replace nodeA.pub() in encrypt()
// decrypt public key from auth
bytes authdecrypted;
decrypt(nodeB.sec(), &authcipher, authdecrypted);
Public node;
bytesConstRef pubk(&authdecrypted[Signature::size + h256::size], Public::size);
pubk.copyTo(node.ref());
bytesConstRef epubk(&ack[0], Public::size);
bytesConstRef nonce(&ack[Public::size], h256::size);
@ -369,7 +380,7 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
}
bytes ackcipher;
encrypt(nodeA.pub(), &ack, ackcipher);
BOOST_REQUIRE(ackcipher.size());
BOOST_REQUIRE_EQUAL(ackcipher.size(), 182);
BOOST_REQUIRE(eA.pubkey());
BOOST_REQUIRE(eB.pubkey());
@ -399,7 +410,7 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
h256 ess;
// todo: ecdh-agree should be able to output bytes
s_secp256k1.agree(eA.seckey(), eBAck, ess);
eA.agree(eBAck, ess);
ess.ref().copyTo(keyMaterial.cropped(0, h256::size));
ssA.ref().copyTo(keyMaterial.cropped(h256::size, h256::size));
// auto token = sha3(ssA);
@ -423,7 +434,7 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
/// Bob (after sending ack)
Secret ssB;
s_secp256k1.agree(nodeB.sec(), nodeA.pub(), ssB);
crypto::ecdh::agree(nodeB.sec(), nodeA.pub(), ssB);
BOOST_REQUIRE_EQUAL(ssA, ssB);
Secret bEncryptK;
@ -466,7 +477,8 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
h256 ess;
// todo: ecdh-agree should be able to output bytes
s_secp256k1.agree(eB.seckey(), eAAuth, ess);
eB.agree(eAAuth, ess);
// s_secp256k1.agree(eB.seckey(), eAAuth, ess);
ess.ref().copyTo(keyMaterial.cropped(0, h256::size));
ssB.ref().copyTo(keyMaterial.cropped(h256::size, h256::size));
// auto token = sha3(ssA);
@ -492,6 +504,9 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
BOOST_REQUIRE_EQUAL(aMacK, bMacK);
BOOST_REQUIRE_EQUAL(aEgressMac, bIngressMac);
BOOST_REQUIRE_EQUAL(bEgressMac, aIngressMac);
}
BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac)
@ -504,6 +519,37 @@ BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac)
}
BOOST_AUTO_TEST_CASE(crypto_rlpxwire)
{
Secret encryptK(sha3("..."));
h256 egressMac(sha3("+++"));
// TESTING: send encrypt magic sequence
bytes magic {0x22,0x40,0x08,0x91};
bytes magicCipherAndMac;
encryptSymNoAuth(encryptK, &magic, magicCipherAndMac, h256());
magicCipherAndMac.resize(magicCipherAndMac.size() + 32);
sha3mac(egressMac.ref(), &magic, egressMac.ref());
egressMac.ref().copyTo(bytesConstRef(&magicCipherAndMac).cropped(magicCipherAndMac.size() - 32, 32));
bytes plaintext;
bytesConstRef cipher(&magicCipherAndMac[0], magicCipherAndMac.size() - 32);
decryptSymNoAuth(encryptK, h256(), cipher, plaintext);
}
BOOST_AUTO_TEST_CASE(crypto_aes128_ctr)
{
Secret k(sha3("0xAAAA"));
string m = "AAAAAAAAAAAAAAAA";
bytesConstRef msg((byte*)m.data(), m.size());
bytes ciphertext;
auto iv = encryptSymNoAuth(k, msg, ciphertext);
bytes plaintext;
decryptSymNoAuth(k, iv, &ciphertext, plaintext);
BOOST_REQUIRE_EQUAL(asString(plaintext), m);
}
BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
{
const int aesKeyLen = 16;
@ -535,7 +581,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
// 68 % 255 should be difference of counter
e.ProcessData(out, in, text.size());
ctr = h128(u128(ctr) + text.size() % 16);
ctr = h128(u128(ctr) + text.size() / 16);
BOOST_REQUIRE(text != original);
cipherCopy = text;

Loading…
Cancel
Save