第五章 加密電路的實現
A. B ENCH . CPP
// bench.cpp
#include "pch.h"
#include "crc.h"
#include "des.h"
#include "blowfish.h"
#include "rc5.h"
#include "tea.h"
#include "bench.h"
#include <time.h>
#include <math.h>
#include <iostream>
#include <iomanip>
USING_NAMESPACE(CryptoPP) USING_NAMESPACE(std)
#ifdef CLOCKS_PER_SEC
static const double CLOCK_TICKS_PER_SECOND = (double)CLOCKS_PER_SEC;
#elif defined(CLK_TCK)
static const double CLOCK_TICKS_PER_SECOND = (double)CLK_TCK;
#else
static const double CLOCK_TICKS_PER_SECOND = 1000000.0;
#endif
static const byte *const key=(byte
*)"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000";
static double logtotal = 0;
static unsigned int logcount = 0;
void OutputResultBytes(const char *name, unsigned long length, double timeTaken) {
double mbs = length / timeTaken / (1024*1024);
cout << "<TR><TH>" << name;
cout << "<TD>" << length;
cout << setiosflags(ios::fixed);
cout << "<TD>" << setprecision(3) << timeTaken;
cout << "<TD>" << setprecision(3) << mbs << endl;
cout << resetiosflags(ios::fixed);
logtotal += log(mbs);
logcount++;
}
void OutputResultOperations(const char *name, const char *operation, bool pc, unsigned long iterations, double timeTaken)
{
cout << "<TR><TH>" << name << " " << operation << (pc ? " with precomputation" : "");
cout << "<TD>" << iterations;
cout << setiosflags(ios::fixed);
cout << "<TD>" << setprecision(3) << timeTaken;
cout << "<TD>" << setprecision(2) << (1000*timeTaken/iterations) << endl;
cout << resetiosflags(ios::fixed);
logtotal += log(iterations/timeTaken);
logcount++;
}
void BenchMark(const char *name, BlockTransformation &cipher, double timeTotal) {
const int BUF_SIZE = RoundDownToMultipleOf(1024U, cipher.OptimalNumberOfParallelBlocks() * cipher.BlockSize());
SecByteBlock buf(BUF_SIZE);
const int nBlocks = BUF_SIZE / cipher.BlockSize();
clock_t start = clock();
unsigned long i=0, length=BUF_SIZE;
double timeTaken;
do {
length *= 2;
for (; i<length; i+=BUF_SIZE)
cipher.ProcessAndXorMultipleBlocks(buf, NULL, buf, nBlocks);
timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
}
while (timeTaken < 2.0/3*timeTotal);
OutputResultBytes(name, length, timeTaken);
}
void BenchMark(const char *name, StreamTransformation &cipher, double timeTotal) {
const int BUF_SIZE=1024;
SecByteBlock buf(BUF_SIZE);
clock_t start = clock();
unsigned long i=0, length=BUF_SIZE;
double timeTaken;
do {
length *= 2;
for (; i<length; i+=BUF_SIZE)
cipher.ProcessString(buf, BUF_SIZE);
timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
}
while (timeTaken < 2.0/3*timeTotal);
OutputResultBytes(name, length, timeTaken);
}
void BenchMark(const char *name, HashTransformation &hash, double timeTotal) {
const int BUF_SIZE=1024;
SecByteBlock buf(BUF_SIZE);
LC_RNG rng(time(NULL));
rng.GenerateBlock(buf, BUF_SIZE);
clock_t start = clock();
unsigned long i=0, length=BUF_SIZE;
double timeTaken;
do {
length *= 2;
for (; i<length; i+=BUF_SIZE)
hash.Update(buf, BUF_SIZE);
timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
}
while (timeTaken < 2.0/3*timeTotal);
OutputResultBytes(name, length, timeTaken);
}
void BenchMark(const char *name, BufferedTransformation &bt, double timeTotal) {
const int BUF_SIZE=1024;
SecByteBlock buf(BUF_SIZE);
LC_RNG rng(time(NULL));
rng.GenerateBlock(buf, BUF_SIZE);
clock_t start = clock();
unsigned long i=0, length=BUF_SIZE;
double timeTaken;
do {
length *= 2;
for (; i<length; i+=BUF_SIZE)
bt.Put(buf, BUF_SIZE);
timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
}
while (timeTaken < 2.0/3*timeTotal);
OutputResultBytes(name, length, timeTaken);
}
void BenchMarkEncryption(const char *name, PK_Encryptor &key, double timeTotal, bool pc=false) {
unsigned int len = 16;
LC_RNG rng(time(NULL));
SecByteBlock plaintext(len), ciphertext(key.CiphertextLength(len));
rng.GenerateBlock(plaintext, len);
clock_t start = clock();
unsigned int i;
double timeTaken;
for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++)
key.Encrypt(rng, plaintext, len, ciphertext);
OutputResultOperations(name, "Encryption", pc, i, timeTaken);
if (!pc && key.GetMaterial().SupportsPrecomputation()) {
key.AccessMaterial().Precompute(16);
BenchMarkEncryption(name, key, timeTotal, true);
} }
void BenchMarkDecryption(const char *name, PK_Decryptor &priv, PK_Encryptor &pub, double timeTotal) {
unsigned int len = 16;
LC_RNG rng(time(NULL));
SecByteBlock ciphertext(pub.CiphertextLength(len));
SecByteBlock plaintext(pub.MaxPlaintextLength(ciphertext.size()));
rng.GenerateBlock(plaintext, len);
pub.Encrypt(rng, plaintext, len, ciphertext);
clock_t start = clock();
unsigned int i;
double timeTaken;
for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++)
priv.Decrypt(rng, ciphertext, ciphertext.size(), plaintext);
OutputResultOperations(name, "Decryption", false, i, timeTaken);
}
void BenchMarkSigning(const char *name, PK_Signer &key, double timeTotal, bool pc=false) {
unsigned int len = 16;
LC_RNG rng(time(NULL));
SecByteBlock message(len), signature(key.SignatureLength());
rng.GenerateBlock(message, len);
clock_t start = clock();
unsigned int i;
double timeTaken;
for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++)
key.SignMessage(rng, message, len, signature);
OutputResultOperations(name, "Signature", pc, i, timeTaken);
if (!pc && key.GetMaterial().SupportsPrecomputation()) {
key.AccessMaterial().Precompute(16);
BenchMarkSigning(name, key, timeTotal, true);
} }
void BenchMarkVerification(const char *name, const PK_Signer &priv, PK_Verifier &pub, double timeTotal, bool pc=false)
{
unsigned int len = 16;
LC_RNG rng(time(NULL));
SecByteBlock message(len), signature(pub.SignatureLength());
rng.GenerateBlock(message, len);
priv.SignMessage(rng, message, len, signature);
clock_t start = clock();
unsigned int i;
double timeTaken;
for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++)
pub.VerifyMessage(message, len, signature, signature.size());
OutputResultOperations(name, "Verification", pc, i, timeTaken);
if (!pc && pub.GetMaterial().SupportsPrecomputation()) {
pub.AccessMaterial().Precompute(16);
BenchMarkVerification(name, priv, pub, timeTotal, true);
} }
void BenchMarkKeyGen(const char *name, SimpleKeyAgreementDomain &d, double timeTotal, bool pc=false) {
LC_RNG rng(time(NULL));
SecByteBlock priv(d.PrivateKeyLength()), pub(d.PublicKeyLength());
clock_t start = clock();
unsigned int i;
double timeTaken;
for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++)
d.GenerateKeyPair(rng, priv, pub);
OutputResultOperations(name, "Key-Pair Generation", pc, i, timeTaken);
if (!pc && d.GetMaterial().SupportsPrecomputation()) {
d.AccessMaterial().Precompute(16);
BenchMarkKeyGen(name, d, timeTotal, true);
} }
void BenchMarkKeyGen(const char *name, AuthenticatedKeyAgreementDomain &d, double timeTotal, bool pc=false) {
LC_RNG rng(time(NULL));
SecByteBlock priv(d.EphemeralPrivateKeyLength()), pub(d.EphemeralPublicKeyLength());
clock_t start = clock();
unsigned int i;
double timeTaken;
for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i++)
d.GenerateEphemeralKeyPair(rng, priv, pub);
OutputResultOperations(name, "Key-Pair Generation", pc, i, timeTaken);
if (!pc && d.GetMaterial().SupportsPrecomputation()) {
d.AccessMaterial().Precompute(16);
BenchMarkKeyGen(name, d, timeTotal, true);
} }
void BenchMarkAgreement(const char *name, SimpleKeyAgreementDomain &d, double timeTotal, bool pc=false) {
LC_RNG rng(time(NULL));
SecByteBlock priv1(d.PrivateKeyLength()), priv2(d.PrivateKeyLength());
SecByteBlock pub1(d.PublicKeyLength()), pub2(d.PublicKeyLength());
d.GenerateKeyPair(rng, priv1, pub1);
d.GenerateKeyPair(rng, priv2, pub2);
SecByteBlock val(d.AgreedValueLength());
clock_t start = clock();
unsigned int i;
double timeTaken;
for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) /
CLOCK_TICKS_PER_SECOND, i+=2) {
d.Agree(val, priv1, pub2);
d.Agree(val, priv2, pub1);
}
OutputResultOperations(name, "Key Agreement", pc, i, timeTaken);
}
void BenchMarkAgreement(const char *name, AuthenticatedKeyAgreementDomain &d, double timeTotal, bool pc=false) {
LC_RNG rng(time(NULL));
SecByteBlock spriv1(d.StaticPrivateKeyLength()), spriv2(d.StaticPrivateKeyLength());
SecByteBlock epriv1(d.EphemeralPrivateKeyLength()), epriv2(d.EphemeralPrivateKeyLength());
SecByteBlock spub1(d.StaticPublicKeyLength()), spub2(d.StaticPublicKeyLength());
SecByteBlock epub1(d.EphemeralPublicKeyLength()), epub2(d.EphemeralPublicKeyLength());
d.GenerateStaticKeyPair(rng, spriv1, spub1);
d.GenerateStaticKeyPair(rng, spriv2, spub2);
d.GenerateEphemeralKeyPair(rng, epriv1, epub1);
d.GenerateEphemeralKeyPair(rng, epriv2, epub2);
SecByteBlock val(d.AgreedValueLength());
clock_t start = clock();
unsigned int i;
double timeTaken;
for (timeTaken=(double)0, i=0; timeTaken < timeTotal; timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND, i+=2)
{
d.Agree(val, spriv1, epriv1, spub2, epub2);
d.Agree(val, spriv2, epriv2, spub1, epub1);
}
OutputResultOperations(name, "Key Agreement", pc, i, timeTaken);
}
//VC60 workaround: compiler bug triggered without the extra dummy parameters template <class T>
void BenchMarkKeyed(const char *name, double timeTotal, T *x=NULL) {
T c;
c.SetKeyWithIV(key, c.DefaultKeyLength(), key);
BenchMark(name, c, timeTotal);
}
//VC60 workaround: compiler bug triggered without the extra dummy parameters template <class T>
void BenchMarkKeyedVariable(const char *name, double timeTotal, unsigned int keyLength, T *x=NULL) {
T c;
c.SetKeyWithIV(key, keyLength, key);
BenchMark(name, c, timeTotal);
}
//VC60 workaround: compiler bug triggered without the extra dummy parameters template <class T>
void BenchMarkKeyless(const char *name, double timeTotal, T *x=NULL) {
T c;
BenchMark(name, c, timeTotal);
}
//VC60 workaround: compiler bug triggered without the extra dummy parameters template <class SCHEME>
void BenchMarkCrypto(const char *filename, const char *name, double timeTotal, SCHEME *x=NULL) {
FileSource f(filename, true, new HexDecoder());
typename SCHEME::Decryptor priv(f);
typename SCHEME::Encryptor pub(priv);
BenchMarkEncryption(name, pub, timeTotal);
BenchMarkDecryption(name, priv, pub, timeTotal);
}
//VC60 workaround: compiler bug triggered without the extra dummy parameters template <class SCHEME>
void BenchMarkSignature(const char *filename, const char *name, double timeTotal, SCHEME *x=NULL)
{
FileSource f(filename, true, new HexDecoder());
typename SCHEME::Signer priv(f);
typename SCHEME::Verifier pub(priv);
BenchMarkSigning(name, priv, timeTotal);
BenchMarkVerification(name, priv, pub, timeTotal);
}
//VC60 workaround: compiler bug triggered without the extra dummy parameters template <class D>
void BenchMarkKeyAgreement(const char *filename, const char *name, double timeTotal, D *x=NULL) {
FileSource f(filename, true, new HexDecoder());
D d(f);
BenchMarkKeyGen(name, d, timeTotal);
BenchMarkAgreement(name, d, timeTotal);
}
void BenchMarkAll(double t) {
#if 1
logtotal = 0;
logcount = 0;
cout << "<TABLE border=1><COLGROUP><COL align=left><COL align=right><COL align=right><COL align=right>" << endl;
cout << "<THEAD><TR><TH>Algorithm<TH>Bytes Processed<TH>Time Taken<TH>Megabytes(2^20 bytes)/Second\n<TBODY>" << endl;
BenchMarkKeyless<CRC32>("CRC-32", t);
BenchMarkKeyed<DES::Encryption>("DES", t);
BenchMarkKeyed<RC5::Encryption>("RC5 (r=16)", t);
BenchMarkKeyed<Blowfish::Encryption>("Blowfish", t);
BenchMarkKeyed<TEA::Encryption>("TEA", t);
cout << "</TABLE>" << endl;
cout << "<TABLE border=1><COLGROUP><COL align=left><COL align=right><COL align=right><COL align=right>" << endl;
cout << "<THEAD><TR><TH>Operation<TH>Iterations<TH>Total Time<TH>Milliseconds/Operation" << endl;
cout << "<TBODY style=\"background: yellow\">" << endl;
BenchMarkKeyAgreement<XTR_DH>("xtrdh171.dat", "XTR-DH 171", t);
BenchMarkKeyAgreement<XTR_DH>("xtrdh342.dat", "XTR-DH 342", t);
BenchMarkKeyAgreement<DH>("dh1024.dat", "DH 1024", t);
BenchMarkKeyAgreement<DH>("dh2048.dat", "DH 2048", t);
BenchMarkKeyAgreement<LUC_DH>("lucd512.dat", "LUCDIF 512", t);
BenchMarkKeyAgreement<LUC_DH>("lucd1024.dat", "LUCDIF 1024", t);
BenchMarkKeyAgreement<MQV>("mqv1024.dat", "MQV 1024", t);
BenchMarkKeyAgreement<MQV>("mqv2048.dat", "MQV 2048", t);
cout << "</TABLE>" << endl;
cout << "Throughput Geometric Average: " << setiosflags(ios::fixed) << exp(logtotal/logcount) << endl;
time_t endTime = time(NULL);
cout << "\nTest ended at " << asctime(localtime(&endTime));
#endif
}