I'm trying to save a public DLIES key to memory and then read it again, but I keep getting exception BER decode error
. I use ArraySink
, ArraySource
and a char[64]
buffer to transfer the key between two CryptoPP::DLIES<>::PublicKey
. I even verify that the public key is good. What am I missing?
Below is the full sample that doesn't work properly. How to modify it so that it'll properly load the key?
#include <iostream>
#include <gfpcrypt.h>
#include <filters.h>
#include <osrng.h>
int main() {
try {
CryptoPP::DefaultAutoSeededRNG rng;
CryptoPP::DLIES<>::PrivateKey privateKey;
privateKey.GenerateRandomWithKeySize(rng, 10);
CryptoPP::DLIES<>::PublicKey publicKey;
privateKey.MakePublicKey(publicKey);
if (!publicKey.Validate(rng, 3)) {
std::cout << "Something wrong with public key." << std::endl;
return 1;
}
byte buf[64];
CryptoPP::ArraySink sink(buf, 64);
publicKey.Save(sink);
CryptoPP::ArraySource source((const char *)buf, sink.TotalPutLength());
CryptoPP::DLIES<>::PublicKey pk;
pk.Load(source);
} catch (CryptoPP::Exception &ex) {
std::cout << ex.what() << std::endl;
return 1;
}
return 0;
}
The problem lied in not setting pumpAll=true
3rd parameter of the ArraySource
constructor. After adding it, it worked. Another working solution was to use ByteQueue
instead. For the sake of completeness, I paste both working examples below.
ArraySource
version:
#include <iostream>
#include <gfpcrypt.h>
#include <filters.h>
#include <osrng.h>
int main() {
try {
CryptoPP::DefaultAutoSeededRNG rng;
CryptoPP::DLIES<>::PrivateKey privateKey;
privateKey.GenerateRandomWithKeySize(rng, 10);
CryptoPP::DLIES<>::PublicKey publicKey;
privateKey.MakePublicKey(publicKey);
if (!publicKey.Validate(rng, 3)) {
std::cout << "Something wrong with sent public key." << std::endl;
return 1;
}
byte buf[64];
CryptoPP::ArraySink sink(buf, 64);
publicKey.Save(sink);
CryptoPP::ArraySource source(buf, sink.TotalPutLength(), true);
CryptoPP::DLIES<>::PublicKey pk;
pk.Load(source);
if (!pk.Validate(rng, 3)) {
std::cout << "Something wrong with received public key." << std::endl;
return 1;
}
} catch (CryptoPP::Exception &ex) {
std::cout << ex.what() << std::endl;
return 1;
}
return 0;
}
ByteQueue
version (which I found more convenient in the end):
#include <iostream>
#include <gfpcrypt.h>
#include <filters.h>
#include <osrng.h>
int main() {
try {
CryptoPP::DefaultAutoSeededRNG rng;
CryptoPP::DLIES<>::PrivateKey privateKey;
privateKey.GenerateRandomWithKeySize(rng, 10);
CryptoPP::DLIES<>::PublicKey publicKey;
privateKey.MakePublicKey(publicKey);
if (!publicKey.Validate(rng, 3)) {
std::cout << "Something wrong with sent public key." << std::endl;
return 1;
}
CryptoPP::ByteQueue queue;
publicKey.Save(queue);
CryptoPP::lword size = queue.TotalBytesRetrievable();
byte buf[64];
queue.Get(buf, size);
CryptoPP::ByteQueue queue2;
queue2.Put(buf, size);
CryptoPP::DLIES<>::PublicKey pk;
pk.Load(queue2);
if (!pk.Validate(rng, 3)) {
std::cout << "Something wrong with received public key." << std::endl;
return 1;
}
} catch (CryptoPP::Exception &ex) {
std::cout << ex.what() << std::endl;
return 1;
}
return 0;
}