2

My question is about a crypto++ constructor and why it is in the state of being "implicitly deleted" even though it follows the examples provided in the documentation.

I am trying to go off of the code provided by the example on Crypto++'s documentation to create a digital signature key pair, but I am having trouble calling the constructor for AutoSeededRandomPool objects. Here is the command I am calling to the terminal:

g++  -I /usr/local/include/ -l cryptopp -std=c++11 -c -o build/account.o src/account.cpp 

I am getting the following error:

error: call to implicitly-deleted copy constructor of 'CryptoPP::AutoSeededRandomPool',
note: copy constructor of 'AutoSeededRandomPool' is implicitly deleted because base
class 'CryptoPP::RandomPool' has a deleted copy constructor

Additionally, I get this unusual message:

clang: warning: -lcryptopp: 'linker' input unused [-Wunused-command-line-argument]

Here is are the files I use to generate the public/private key pair. They pretty much follow the example:

DSA::PrivateKey create_private_key(AutoSeededRandomPool rng) {
  DSA::PrivateKey private_Key;
  private_Key.GenerateRandomWithKeySize(rng, 1024);
  return private_Key;
}

DSA::PublicKey create_public_key(DSA::PrivateKey private_key, AutoSeededRandomPool rng) {
  DSA::PublicKey public_Key;
  public_Key.AssignFrom(private_key);
  if (!private_key.Validate(rng, 3) || !public_Key.Validate(rng, 3))
  {
    throw std::runtime_error("DSA key generation failed");
  }
  return public_Key;
}

I declare and initialize the AutoSeededRandomPool object in a constructor as follows:

account::account() {
  balance = 0;
  AutoSeededRandomPool rng;
  private_key = utils::create_private_key(rng);
  public_key = utils::create_public_key(private_key, rng);
}

I have linked in the libraries necessary for this, and I am linking them in when I call g++. Additionally, if anyone knows if there are any more detailed examples of Crypto++ code, those resources would be greatly appreciated.

jww
  • 97,681
  • 90
  • 411
  • 885
Marty
  • 133
  • 1
  • 2
  • 7
  • 2
    Why don't you try passing the parameters by reference rather than value? If you pass them by value, that implicitly calls the copy constructor, and apparently they aren't copyable. – Chris Beck Jul 25 '17 at 03:37
  • Thanks, that was it. I did not know that fact about copy constructors. – Marty Jul 25 '17 at 13:54

1 Answers1

1
 g++ -I /usr/local/include/ -l cryptopp -std=c++11 -c -o build/account.o src/account.cpp 

clang: warning: -lcryptopp: 'linker' input unused

Try:

g++ ... src/account.cpp -c -o build/account.o

Omit -l cryptopp. It is only needed during link.


DSA::PrivateKey create_private_key(AutoSeededRandomPool rng) {
  DSA::PrivateKey private_Key;
  private_Key.GenerateRandomWithKeySize(rng, 1024);
  return private_Key;
}

error: call to implicitly-deleted copy constructor of 'CryptoPP::AutoSeededRandomPool', note: copy constructor of 'AutoSeededRandomPool' is implicitly deleted because base class 'CryptoPP::RandomPool' has a deleted copy constructor

Pass rng by reference:

DSA::PrivateKey create_private_key(AutoSeededRandomPool& rng) {
    ...
}

Do it in both create_private_key and create_public_key.

The reason is, AutoSeededRandomPool base class is RandomPool, and RandomPool base class is NotCopyable. NotCopyable hides copy and assignment by making them private. I guess that's where the "implicit" part comes from the compiler error.

class RandomPool : public RandomNumberGenerator, public NotCopyable
{
    ...
}

IF you don't want to pass by reference, then create one locally. There are certain reasons why you want to do this when generating a private key. See Cryptography Engineering: Design Principles and Practical Applications for more details.

DSA::PrivateKey create_private_key() {
  AutoSeededRandomPool rng;
  DSA::PrivateKey private_Key;
  private_Key.GenerateRandomWithKeySize(rng, 1024);
  return private_Key;
}

Related, when you link, place -lcryptopp at the end of the command. Something like:

g++ -o myprog -std=c++11 build/account.o build/some-other-object.o -lcryptopp -pthread

Order matters because LD is a single pass linker. Libraries always go at the end. You can work around it with options like -( and --start-group, but its easy to remember to place libraries at the end.


Some more of the C++11 backstory is, when you experience copy constructor implicitly deleted, you usually define one in your class. See, for example, Use of deleted function error.

However, in the case of AutoSeededRandomPool, we don't want them copied for several reasons. The Crypto++ Algorithm class, which is a base class of AutoSeededRandomPool, has a Clone. However, we don't want the generator cloned, either. Again, see Cryptography Engineering: Design Principles and Practical Applications.

jww
  • 97,681
  • 90
  • 411
  • 885