So I have a little unusual situation, that my experience with templates and tutorials doesn’t seem to cover.
I am writing an program that automatically signs messages for another program that is incapable but has a limited API. There is a configuration file that contains a string telling my program what hash to use to sign a message.
This string is stored in a signatureAlgorithm object which stores a digest, the size the digest should be, and offers a few options for the encoding of the digest.
I am using the Crypto++ library for the hashing functions.
Right now I have a large set of if/else if statements and three commands in each one depending on what the string says the algorithm should be, as shown below:
void signatureAlgorithm::createDigest(string input)
{
bool digestFail = false;
if (_algorithm == "md5")
{
//byte digest[ CryptoPP::MD5::DIGESTSIZE ];
_digestSize = (CryptoPP::MD5::DIGESTSIZE);
_digest = new byte[ _digestSize ];
CryptoPP::MD5().CalculateDigest( _digest, (byte*) input.c_str(), input.length() );
}
.....
else if (_algorithm == "sha256")
{
_digestSize = (CryptoPP::SHA256::DIGESTSIZE);
_digest = new byte[ _digestSize ];
CryptoPP::SHA256().CalculateDigest( _digest, (byte*) input.c_str(), input.length() );
}
else if (_algorithm == "sha512")
{
_digestSize = (CryptoPP::SHA512::DIGESTSIZE);
_digest = new byte[ _digestSize ];
CryptoPP::SHA512().CalculateDigest( _digest, (byte*) input.c_str(), input.length() );
}
else
digestFail = true;
if (!digestFail)
_ready = true;
else
_ready = false;
}
_digestSize stores the digest size in the object, as _digest does for the bytes of the digest (bytes are typedef const unsigned char*), and _ready is used in other functions to determine of the value has been digested before giving it to a calling program, or instead returning an error to the program.
I eventually plan to switch to a map to make things more efficient and tidier, however before I do I have to find a way to make the setting of _digestSize and the calling of CreateDigest() more generic. I am trying to avoid modifying the library as I want to maintain the FIPS status of Crypto++ in compiled form in the final release, but for now I’m just testing using the source if that makes a difference.
I thought about templates, with the inner section of each if statement just setting the value, but I can’t find an example of the template being used in such a fashion. I find them for making classes where there are other functions, but in this case I just need to be able to make a generic class that simply points to another class if I am thinking right here.
pseudo-code for what I’m trying to do:
class tempClass {};
if (_algorithm == "md5")
{
tempClass = CryptoPP::MD5
}
......
else
digestFail = true;
_digestSize = (tempClass::DIGESTSIZE);
_digest = new byte[_digestSize];
tempClass().CalculateDigest( _digest, (byte*) input.c_str(), input.length() );
-Jimmy
EDIT: While in the comments I stated that inheritance wouldn’t work because of the forking in the class tree, it turns out that the documentation I’ve been using is for the most recent version. The version I’m using for testing and the FIPS version are older, from before functions like MD5 etc were split out into a separate “weak” structure.
EDIT 2: However, I’m still curious as to if there were a way to go about this even if the classes were forked and didn’t inherit CalculateDigest from the same place.
EDIT 3: John Bandela answered the question, but I just had to change what he gave me a little bit. Changes are in the comments for the answer. Thanks all!
Break out the code into a template function like this
// Assuming _digest and _digest size are class members;
Then in your createDigest function do this
Off topic, but you may want to consider using a vector instead of byte*