LUC Cryptography

From Crypto++ Wiki
Jump to navigation Jump to search
LUC Cryptography
Documentation
#include <cryptopp/luc.h>

LUC Cryptography is a public-key cryptosystem designed by P.J. Smith and based on Lucas sequences. It can be used for encryption and signatures.

Background

Crypto++ exposes most LUC encrpytion and signatures operations through luc.h. There's a LUCES (encryption scheme), LUCSS (signature scheme) and LUC_IES (integrated encryption system, with key agreement and mask function).

Keys

Operations on keys, such as generating, validating, loading, saving, importing, exporting, and formats are discussed in detail at Keys and Formats.

Crypto++ LUC keys are typedef'd in luc.h as follows.

struct LUC
{
    static std::string StaticAlgorithmName() {return "LUC";}
    typedef LUCFunction PublicKey;
    typedef InvertibleLUCFunction PrivateKey;
}

To generate a key pair, InvertibleLUCFunction offers GenerateRandomWithKeySize:

GenerateRandomWithKeySize (RandomNumberGenerator &rng, unsigned int keySize)

The parameters to the function are a RandomNumberGenerator and the modulus size specified in bits. GenerateRandomWithKeySize calls GenerateRandom with the modulus size encoded as a NameValuePairs.

In much of the sample code, InvertibleLUCFunction is used as follows to create a logical separation for demonstration purposes.

///////////////////////////////////////
// Generate Parameters
InvertibleLUCFunction params;
params.GenerateRandomWithKeySize(rng, 3072);

///////////////////////////////////////
// Create Keys
LUC::PrivateKey privateKey(params);
LUC::PublicKey publicKey(params);

In practice, LUC::PrivateKey could be used instead of InvertibleLUCFunction (to improve readability); and LUCES_PKCS1v15_Encryptor, LUCES_OAEP_SHA_Encryptor, and friends should be used. A more detailed treatment of keys, generation, loading, saving, and formats can be found at Keys and Formats.

///////////////////////////////////////
// Create Keys
LUC::PrivateKey privateKey;
privateKey.GenerateRandomWithKeySize(rng, 3072);

LUC::PublicKey publicKey(privateKey);

Once the keys are created, they can be passed to Encryptors, Decryptors, Signers, and Verifiers.

To persist the keys to disk in the most inter-operable manner, use the Save function. If loading from disk, use the Load function. A more complete treatment of saving and loading keys is covered in Keys and Formats.

If you need to import the {n,e,d} private key or {n,e} public key into Crypto++, use Initialize. Both LUC::PublicKey and LUC::PrivateKey provide the function overloads.

Encryption Schemes

The high level LUC Encryption Scheme are exposed through LUCES, which is defined as follows. The template parameter, STANDARD, simply specifies additional algorithms. For example, when PKCS processing is required, PKCS1v15 is specified as the parameter.

template <class STANDARD>
struct LUCES : public TF_ES<STANDARD, LUC>
{ };

The TF_ES class exposes the functionality that is often used when working with LUC encryption. TF stands for trapdoor function, and ES stands for encryption scheme. There is some hand waiving here - at least two layers of templates exist before encountering TF_EncryptorBase and TF_DecryptorBase in cryptlib.h. To ease use of the library, a typedef are offered.

typedef LUCES<OAEP<SHA> >::Decryptor LUCES_OAEP_SHA_Decryptor;
typedef LUCES<OAEP<SHA> >::Encryptor LUCES_OAEP_SHA_Encryptor;

Signature Schemes

The high level LUC Signature Schemes are exposed through LUCSS, which is defined as follows.

template <class STANDARD, class H>
struct LUCSS : public TF_SS<STANDARD, H, LUC>
{ };

As with LUCES, LUCSS needs a STANDARD. TF stands for trapdoor function, and SS stands for signature scheme. In addition to the STANDARD parameter, a one way hash function must be specified through H. The classes of interest for signers and verifiers are PK_Signer and PK_Verifier from cryptlib.h. The later classes offer familiar functions such as MaxSignatureLength, SignMessage, and VerifyMessage.

The Crypto++ LUC implementation of a Signature Scheme with Appendix (SSA) is typedef'd as follows.

typedef LUCSS<PKCS1v15, SHA>::Signer LUCSSA_PKCS1v15_SHA_Signer;
typedef LUCSS<PKCS1v15, SHA>::Verifier LUCSSA_PKCS1v15_SHA_Verifier;

The Crypto++ LUC implementation of a Signature Scheme with Recovery (PSSR) is similar to SSA. However, there are no typedef's so the objects are declared using template syntax. Below, PSSR (from pssr.h) is specified (the recovery mechanism), and a hash is specified.

LUCSS<PSS, SHA1>::Signer signer;
LUCSS<PSS, SHA1>::Verifier verifier;

If Whirlpool were desired, the following would be performed.

LUCSS<PSS, Whirlpool>::Signer signer;
LUCSS<PSS, Whirlpool>::Verifier verifier;

If you want to use a larger hash (like SHA-256) then the declaration would be:

LUCSS<PSS, SHA256>::Signer signer;
LUCSS<PSS, SHA256>::Verifier verifier;

Regardless of the type of signature (PSSR vs SSA), the signers and verifiers are most easily constructed using the private key or the public key.

// Generate or Load keys
LUC::PrivateKey privateKey;
LUC::PublicKey publicKey;
...

LUCSS<PSS, SHA1>::Signer signer(privateKey);
// Create signature
...

LUCSS<PSS, SHA1>::Verifier verifier(publicKey);
// Verify signature on message
...

Sample Programs

Below offers sample code to exercise some of the operations on LUC.

Key Generation

///////////////////////////////////////
// Pseudo Random Number Generator
AutoSeededRandomPool rng;

///////////////////////////////////////
// Generate Parameters
InvertibleLUCFunction params;
params.GenerateRandomWithKeySize(rng, 3072);

///////////////////////////////////////
// Generated Parameters
const Integer& n = params.GetModulus();
const Integer& p = params.GetPrime1();
const Integer& q = params.GetPrime2();
const Integer& e = params.GetPublicExponent();
const Integer& u = params.GetMultiplicativeInverseOfPrime2ModPrime1();

///////////////////////////////////////
// Dump
cout << "LUC Parameters:" << endl;
cout << " n: " << n << endl;
cout << " p: " << p << endl;
cout << " q: " << q << endl;
cout << " e: " << e << endl;
cout << " u: " << u << endl;
cout << endl;

///////////////////////////////////////
// Create Keys
LUC::PrivateKey privateKey(params);
LUC::PublicKey publicKey(params);

///////////////////////////////////////
// Save Keys
FileSink fs1("lucs-private.der", true);
privateKey.DEREncode(fs1);
        
FileSink fs2("lucs-public.der", true);
publicKey.DEREncode(fs2);

And:

///////////////////////////////////////
// Pseudo Random Number Generator
AutoSeededRandomPool rng;

///////////////////////////////////////
// Generate Parameters
InvertibleLUCFunction params;
params.GenerateRandomWithKeySize(rng, 3072);

///////////////////////////////////////
// Create Signer and Verifier
LUCSS<PSS, SHA256>::Signer signer(params);
LUCSS<PSS, SHA256>::Verifier verifier(params);

///////////////////////////////////////
// Save Keys
FileSink fs1("lucs-private.der", true);
signer.AccessKey().DEREncode(fs1);
        
FileSink fs2("lucs-public.der", true);
verifier.AccessKey().DEREncode(fs2);

Encryption Scheme (OAEP using SHA)

The following code demonstrates LUC encryption using OAEP.

////////////////////////////////////////////////
// Generate keys
AutoSeededRandomPool rng;

InvertibleLUCFunction params;
params.GenerateRandomWithKeySize(rng, 3072);

LUC::PrivateKey privateKey(params);
LUC::PublicKey publicKey(params);

string plain="LUC Encryption", cipher, recovered;

////////////////////////////////////////////////
// Encryption
LUCES_OAEP_SHA_Encryptor e(publicKey);

StringSource ss1(plain, true,
    new PK_EncryptorFilter(rng, e,
        new StringSink(cipher)
   ) // PK_EncryptorFilter
); // StringSource

////////////////////////////////////////////////
// Decryption
LUCES_OAEP_SHA_Decryptor d(privateKey);

StringSource ss2(cipher, true,
    new PK_DecryptorFilter(rng, d,
        new StringSink(recovered)
   ) // PK_DecryptorFilter
); // StringSource

cout << "Recovered plain text" << endl;

Signature Scheme (PKCS v1.5)

Though similar to LUC-SSA, LUCSSA_PKCS1v15_SHA_Signer and LUCSSA_PKCS1v15_SHA_Verifier use PKCS v1.5 padding.

// Generate or Load keys
LUC::PrivateKey privateKey = ...;
LUC::PublicKey publicKey = ...;

// Message
string message = "LUC Signature", signature;

////////////////////////////////////////////////
// Sign and Encode
LUCSSA_PKCS1v15_SHA_Signer signer(privateKey);

StringSource ss1(message, true, 
    new SignerFilter(rng, signer,
        new StringSink(signature)
   ) // SignerFilter
); // StringSource

////////////////////////////////////////////////
// Verify and Recover
LUCSSA_PKCS1v15_SHA_Verifier verifier(publicKey);

StringSource ss2(message+signature, true,
    new SignatureVerificationFilter(
        verifier, NULL,
        SignatureVerificationFilter::THROW_EXCEPTION
   ) // SignatureVerificationFilter
); // StringSource

cout << "Verified signature on message" << endl;