HashVerificationFilter

From Crypto++ Wiki
Jump to: navigation, search

A HashVerificationFilter is a filter that verifies a digest on a message. The companion class is the HashFilter.

The HashVerificationFilter decompressor takes a pointer to a BufferedTransformation. Because a pointer is taken, the HashVerificationFilter owns the attached transformation, and therefore will destroy it. See ownership for more details.

Construction

HashVerificationFilter (HashTransformation &hm,
                        BufferedTransformation *attachment=NULL,
                        word32 flags=DEFAULT_FLAGS)

hm is a hash, such as Whirlpool or SHA.

attachment is a BufferedTransformation, such as another filter or sink. If attachment is NULL, then the HashVerificationFilter object will internally accumulate the output byte stream.

flags is most interesting. The values and their meanings are as follows. Note that HASH_AT_BEGIN and HASH_AT_END are mutually exclusive. If you set putMessage=true with a HashFilter, then be sure to specify HASH_AT_END.

  • DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT
  • HASH_AT_END (0)
    • specifies the hash value will be located at the end of the message
  • HASH_AT_BEGIN (1)
    • specifies the hash value will be located at the beginning of the message
  • PUT_MESSAGE (2)
    • specifies whether the message should be forwarded to the attached transformation
  • PUT_HASH (4)
    • specifies whether the the hash should be forwarded to the attached transformation
  • PUT_RESULT (8)
    • specifies whether the result of the verification (a boolean) should be forwarded to the attached transformation
  • THROW_EXCEPTION (16)
    • specifies whether an exception should be thrown if digest verification fails

Verification with THROW_EXCEPTION

The sample program below demonstrates a HMAC with SHA256 using filters (see pipelining). The HashVerificationFilter uses the THROW_EXCEPTION flag, which causes Crypto++ to throw an exception on verification failure.

AutoSeededRandomPool prng;

SecByteBlock key(16);   // SHA256::BLOCKSIZE will also work
prng.GenerateBlock(key, key.size());

string plain = "HMAC Test";
string mac, encoded;

/*********************************\
\*********************************/

try
{
    HMAC< SHA256 > hmac(key, key.size());

    StringSource ss(plain, true, 
        new HashFilter(hmac,
            new StringSink(mac)
        ) // HashFilter      
    ); // StringSource
}
catch(const CryptoPP::Exception& e)
{
    cerr << e.what() << endl;
    exit(1);
}

/*********************************\
\*********************************/

try
{
    HMAC< SHA256 > hmac(key, key.size());
    const int flags = HashVerificationFilter::THROW_EXCEPTION | HashVerificationFilter::HASH_AT_END;
    
    StringSource ss(plain + mac, true, 
        new HashVerificationFilter(hmac, NULL, flags)
    ); // StringSource

    cout << "Verified message" << endl;
}
catch(const CryptoPP::Exception& e)
{
    cerr << e.what() << endl;
    exit(1);
}

Testing the try/catch block is easily accomplished by tampering with the message or the MAC:

HMAC< SHA256 > hmac(key, key.size());

// Tamper with message
plain[0] ^= 0x01;

// Tamper with MAC
mac[0] ^= 0x01;

StringSource ss(plain + mac, true, 
    new HashVerificationFilter(hmac, NULL, flags)
); // StringSource

Verification without THROW_EXCEPTION

The sample program below demonstrates verification using PUT_RESULT. When using the flag, the result is forwarded to the attached buffered transformation (attachment), which is a bool wrapped using an ArraySink.

AutoSeededRandomPool prng;

SecByteBlock key(16);
prng.GenerateBlock(key, key.size());

string plain = "HMAC Test";
string mac, encoded;

/*********************************\
\*********************************/

HMAC< SHA256 > hmac1(key, key.size());

StringSource ss(plain, true, 
    new HashFilter(hmac1,
        new StringSink(mac)
    ) // HashFilter      
); // StringSource

/*********************************\
\*********************************/

HMAC< SHA256 > hmac2(key, key.size());
    
bool result = false;
StringSource ss(plain + mac, true, 
    new HashVerificationFilter(hmac2,
        new ArraySink((byte*)&result, sizeof(result)),
        PUT_RESULT | HASH_AT_END
    ) // HashVerificationFilter
); // StringSource

if(result)
    cout << "Verified message" << endl;
else
    cerr << "Failed to verify message" << endl;

Downloads

CMAC-AES-Filter.zip - Demonstrates an AES based CMAC and verification with filters

HMAC-SHA-Filter.zip - Demonstrates a SHA256 based HMAC and verification with filters