Fork for poking around in the original "client implementation for p≡p update server".
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
downloadclient/UpdateStream.cc

117 lines
3.6 KiB

// this file is under GNU General Public License 3.0
// see LICENSE.txt
#include "UpdateStream.hh"
#include <cryptopp/ripemd.h>
#include <cryptopp/hmac.h>
#include <cryptopp/filters.h>
#include <cryptopp/hex.h>
#include <cryptopp/osrng.h>
namespace pEp {
namespace UpdateClient {
using namespace CryptoPP;
using byte = CryptoPP::byte;
UpdateDevice::UpdateDevice(const product p)
: _https({HTTPSDevice()}, ios::binary), _p(p),
_key(32), _src(nullptr), _str(nullptr)
{
}
UpdateDevice::UpdateDevice(const UpdateDevice& second)
: _https({HTTPSDevice()}, ios::binary), _p(second._p),
_key(32), _src(nullptr), _str(nullptr)
{
}
UpdateDevice::~UpdateDevice()
{
close();
delete _src;
delete _str;
}
void UpdateDevice::open(CryptoPP::RSA::PublicKey update_key, notifyRead_t notifyRead)
{
CryptoPP::RSAES< CryptoPP::OAEP<CryptoPP::SHA256> >::Encryptor update_encryptor(update_key);
string url = _p.url;
CryptoPP::AutoSeededRandomPool rnd;
rnd.GenerateBlock( _key, _key.size() );
string delivery_key = string((char *) _key.data(), _key.size());
string delivery_key_enc;
StringSource update_encrypt(delivery_key, true,
new PK_EncryptorFilter(rnd, update_encryptor,
new StringSink(delivery_key_enc)
)
);
HexEncoder encoder;
encoder.Put((byte*) delivery_key_enc.c_str(), delivery_key_enc.length());
encoder.MessageEnd();
word64 size = encoder.MaxRetrievable();
string _delivery_key_enc;
if (size && size <= SIZE_MAX)
{
_delivery_key_enc.resize(size);
encoder.Get((byte*) _delivery_key_enc.data(), _delivery_key_enc.size());
}
url += "&challenge=" + _delivery_key_enc;
_https->open(url, notifyRead);
byte iv[12];
_https->read((char *) iv, sizeof(iv));
if (filename() == "") {
string snk;
_delivery_decryptor.SetKeyWithIV(_key, _key.size(), iv, sizeof(iv));
_src = new CryptoPP::FileSource(_https, true,
new CryptoPP::AuthenticatedDecryptionFilter(
_delivery_decryptor,
new CryptoPP::StringSink(snk)
)
);
delete _str;
_str = new stringstream(snk);
}
else {
_delivery_decryptor.SetKeyWithIV(_key, _key.size(), iv, sizeof(iv));
_src = new CryptoPP::FileSource(_https, true,
new CryptoPP::AuthenticatedDecryptionFilter(
_delivery_decryptor,
new CryptoPP::FileSink(filename().c_str(), true)
)
);
delete _str;
_str = nullptr;
}
}
void UpdateDevice::close()
{
_https->close();
delete _src;
_src = nullptr;
delete _str;
_str = nullptr;
}
streamsize UpdateDevice::read(char* s, streamsize n)
{
if (!_str || _str->eof())
return -1;
_str->read(s, n);
return _str->gcount();
}
}
}