LSH

From Crypto++ Wiki
Jump to navigation Jump to search
LSH-256, LSH-512
Documentation
#include <cryptopp/lsh.h>

LSH-256 and LSH-512 are a family of cryptographic hash functions designed by Dong-Chan Kim, Deukjo Hong, Jung-Keun Lee, Woo-Hwan Kim and Daesung Kwon. They are part of South Korea's cryptographic portfolio KS X 3262. The hashes use wide-pipe Merkle-Damgård construction with one-zeros padding. Also see LSH: A New Fast Secure Hash Function Family.

The internal block size of LSH-256 and LSH-512 are large at 128 and 256 bytes, respectively. The numbers were taken from the reference implementation hmac.c (see LSH256_MSG_BLK_BYTE_LEN and LSH512_MSG_BLK_BYTE_LEN). The block size is used for HMACs.

The library's implementation closely follows the reference implementation. However, we had to modify load_msg_blk to accommodate unaligned loads (the reference implementation only performed a type cast). load_msg_blk is on the critical path because it is called by compress. Because of the load fix we may not not hit the advertised benchmark speeds (unless the compiler elides a memcpy).

LSH was added to Crypto++ 8.6. The implementation is byte oriented, and it does not process partial bits. Also see Issue #1025, Add LSH-256 and LSH-512 hash functions and Commit 11eee26d76f4 (and friends).

Crypto++ offers several ciphers from Korea Internet & Security Agency portfolio. The algorithms include ARIA, HIGHT, LEA, LSH and SEED. Additionally the library offers CHAM.

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.

If you experience failed self tests using GCC, then we are probably hitting GCC Issue 82735, _mm256_zeroupper does not invalidate previously computed registers. GCC does not handle calls to zeroupper properly.

Sample Programs

There are five sample programs. The first prints information about the hash. The second creates a hash using LSH256 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 LSH256, but you can swap-in any hash function, like LSH512, PanamaHash, SM3 or BLAKE2b.

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

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

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

    LSH256 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.

$ ./test.exe
Name: LSH-256
Digest size: 32
Block size: 128

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;

LSH256 hash;
hash.Update((const byte*)&msg[0], 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: F16C5D314310E71925AC8099938CC4275AD18B1EADDB90F7589E68837FE885F1

You can also obtain a truncated hash rather than the full hash using TruncatedFinal. Note: it is not clear if a truncated hash is valid for LSH. Crypto++ code will assert in debug builds if you use a truncated hash.

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

hash.Update((const byte*)&msg[0], 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: F16C5D314310E71925AC8099938CC427

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;

LSH256 hash;
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: F16C5D314310E71925AC8099938CC4275AD18B1EADDB90F7589E68837FE885F1

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.

LSH256 hash;
hash.Update((const byte*)&msg[0], 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: F16C5D314310E71925AC8099938CC4275AD18B1EADDB90F7589E68837FE885F1
Verified hash over message

Downloads

No downloads available.