Tiger

From Crypto++ Wiki
Jump to navigation Jump to search
Tiger
Documentation
#include <cryptopp/tiger.h>

Tiger is cryptographic hash function by designed by Ross Anderson and Eli Biham. There are at least two different versions of Tiger. The first is the original algorithm, and the second is a revision that fixed a padding bug. Also see Tiger: A Fast New Cryptographic Hash Function and Ross Anderson's homepage.

Crypto++ provides the original Tiger hash that was submitted to the NESSIE project. The implementation is different from the revised Tiger2 hash. The original Tiger test vectors are available at test-vectors-nessie-format.dat. The Crypto++ test vectors are available in validat5.cpp.

All Crypto++ hashes derive from HashTransformation. The base class provides functions like Update, Final and Verify. You can swap-in any hash for any other hash in your program. You can also use ChannelSwitch to send data to multiple hashes at the same time.

Sample Programs

There are five sample programs. The first prints information about the hash. The second creates a hash using Tiger class. The third creates a hash using a pipeline. The fourth and fifth examples show how to verify an existing digest.

The examples below use Tiger, but you can swap-in any hash function, like PanamaHash, SM3 or BLAKE2s.

The first example dumps the name, digest size and internal block size of the hash.

#include "cryptlib.h"
#include "tiger.h"
#include <iostream>

int main (int argc, char* argv[])
{
    using namespace CryptoPP;

    Tiger hash;	
    std::cout << "Name: " << hash.AlgorithmName() << std::endl;
    std::cout << "Digest size: " << hash.DigestSize() << std::endl;
    std::cout << "Block size: " << hash.BlockSize() << std::endl;

    return 0; 
}

Running the program results in the following. In general you should use DigestSize and avoid BlockSize. BlockSize is usually not required by a program. In the case of SHAKE the block size is the rate r.

$ ./test.exe
Name: Tiger
Digest size: 24
Block size: 64

The second example creates a hash using the hash object and member functions. You add data using Update and you calculate the hash using Final. Calling Final resets the hash so you don't need to do it manually.

using namespace CryptoPP;
HexEncoder encoder(new FileSink(std::cout));

std::string msg = "Yoda said, Do or do not. There is not try.";
std::string digest;

Tiger hash;
hash.Update((const byte*)msg.data(), msg.size());
digest.resize(hash.DigestSize());
hash.Final((byte*)&digest[0]);

std::cout << "Message: " << msg << std::endl;

std::cout << "Digest: ";
StringSource(digest, true, new Redirector(encoder));
std::cout << std::endl;

Running the program results in the following.

$ ./test.exe
Message: Yoda said, Do or do not. There is not try.
Digest: B56AA0DC5A56765BB88E59734E6F3ED349F901AB892E7D7E

You can also obtain a truncated hash rather than the full hash using TruncatedFinal.

std::cout << "Message: " << msg << std::endl;

hash.Update((const byte*)msg.data(), msg.size());
digest.resize(hash.DigestSize()/2);
hash.TruncatedFinal((byte*)&digest[0], digest.size());

std::cout << "Digest: ";
StringSource(digest, true, new Redirector(encoder));
std::cout << std::endl;

The program produces the following result.

$ ./test.exe
Message: Yoda said, Do or do not. There is not try.
Digest: B56AA0DC5A56765BB88E5973

Using a pipeline produces the same result. It relieves you of calling Update and Final manually. The code also uses a HashFilter, which has its own wiki page at HashFilter.

std::string msg = "Yoda said, Do or do not. There is not try.";
std::string digest;

StringSource(msg, true, new HashFilter(hash, new StringSink(digest)));

std::cout << "Message: " << msg << std::endl;

std::cout << "Digest: ";
StringSource(digest, true, new Redirector(encoder));
std::cout << std::endl;

Running the program results in the following.

$ ./test.exe
Message: Yoda said, Do or do not. There is not try.
Digest: B56AA0DC5A56765BB88E59734E6F3ED349F901AB892E7D7E

The fourth program verifies an existing hash using the hash object. Notice the program proceeds as if the hash is going to be calculated. But rather than calling Final to retrieve the hash, Verify is called to verify the existing hash.

Tiger hash;
hash.Update((const byte*)msg.data(), msg.size());
bool verified = hash.Verify((const byte*)digest.data());

if (verified == true)
    std::cout << "Verified hash over message" << std::endl;
else
    std::cout << "Failed to verify hash over message" << std::endl;

The final program verifies an existing hash using a pipeline. The code uses a HashVerificationFilter, which has its own wiki page at HashVerificationFilter.

bool result;
StringSource(digest+msg, true, new HashVerificationFilter(hash,
                 new ArraySink((byte*)&result, sizeof(result))));

if (result == true)
    std::cout << "Verified hash over message" << std::endl;
else
    std::cout << "Failed to verify hash over message" << std::endl;

Running the program results in the following output.

$ ./test.exe
Message: Yoda said, Do or do not. There is not try.
Digest: B56AA0DC5A56765BB88E59734E6F3ED349F901AB892E7D7E
Verified hash over message

Downloads

No downloads available.