📄 fipsalgt.cpp
字号:
// fipsalgt.cpp - written and placed in the public domain by Wei Dai
// This file implements the various algorithm tests needed to pass FIPS 140 validation.
// They're preserved here (commented out) in case Crypto++ needs to be revalidated.
#if 0
#include "dll.h"
USING_NAMESPACE(CryptoPP)
USING_NAMESPACE(std)
class LineBreakParser : public AutoSignaling<Bufferless<Filter> >
{
public:
LineBreakParser(BufferedTransformation *attachment=NULL, byte lineEnd='\n')
: AutoSignaling<Bufferless<Filter> >(attachment), m_lineEnd(lineEnd) {}
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
{
if (!blocking)
throw BlockingInputOnly("LineBreakParser");
unsigned int i, last = 0;
for (i=0; i<length; i++)
{
if (begin[i] == m_lineEnd)
{
AttachedTransformation()->Put2(begin+last, i-last, GetAutoSignalPropagation(), blocking);
last = i+1;
}
}
if (last != i)
AttachedTransformation()->Put2(begin+last, i-last, 0, blocking);
if (messageEnd && GetAutoSignalPropagation())
{
AttachedTransformation()->MessageEnd(GetAutoSignalPropagation()-1, blocking);
AttachedTransformation()->MessageSeriesEnd(GetAutoSignalPropagation()-1, blocking);
}
return 0;
}
private:
byte m_lineEnd;
};
class TestDataParser : public Unflushable<FilterWithInputQueue>
{
public:
enum DataType {OTHER, COUNT, KEY_T, IV, INPUT, OUTPUT};
TestDataParser(std::string algorithm, std::string test, std::string mode, unsigned int feedbackSize, bool encrypt, BufferedTransformation *attachment)
: Unflushable<FilterWithInputQueue>(attachment)
, m_algorithm(algorithm), m_test(test), m_mode(mode), m_feedbackSize(feedbackSize)
, m_firstLine(true), m_blankLineTransition(0)
{
m_nameToType["COUNT"] = COUNT;
m_nameToType["KEY"] = KEY_T;
m_nameToType["KEYs"] = KEY_T;
m_nameToType["key"] = KEY_T;
m_nameToType["IV"] = IV;
m_nameToType["IV1"] = IV;
m_nameToType["CV"] = IV;
m_nameToType["CV1"] = IV;
m_nameToType["IB"] = IV;
m_nameToType["TEXT"] = INPUT;
m_nameToType["RESULT"] = OUTPUT;
SetEncrypt(encrypt);
if (m_algorithm == "DSS")
{
if (m_test == "prime")
m_trigger = "Prime";
else if (m_test == "pqg")
m_trigger = "N";
else if (m_test == "xy")
m_trigger = "G";
else if (m_test == "gensig")
m_trigger = "Msg";
else if (m_test == "versig")
m_trigger = "Sig";
else if (m_test == "verpqg")
m_trigger = "c";
}
}
void SetEncrypt(bool encrypt)
{
m_encrypt = encrypt;
if (encrypt)
{
m_nameToType["PLAINTEXT"] = INPUT;
m_nameToType["CIPHERTEXT"] = OUTPUT;
m_nameToType["PT"] = INPUT;
m_nameToType["CT"] = OUTPUT;
}
else
{
m_nameToType["PLAINTEXT"] = OUTPUT;
m_nameToType["CIPHERTEXT"] = INPUT;
m_nameToType["PT"] = OUTPUT;
m_nameToType["CT"] = INPUT;
}
if (m_algorithm == "AES")
{
if (encrypt)
{
m_trigger = "PLAINTEXT";
m_typeToName[OUTPUT] = "CIPHERTEXT";
}
else
{
m_trigger = "CIPHERTEXT";
m_typeToName[OUTPUT] = "PLAINTEXT";
}
m_count = 0;
}
}
protected:
void OutputData(std::string &output, const std::string &key, const std::string &data)
{
output += key;
output += "= ";
output += data;
output += "\n";
}
void OutputData(std::string &output, const std::string &key, int data)
{
OutputData(output, key, IntToString(data));
}
void OutputData(std::string &output, const std::string &key, const SecByteBlock &data)
{
output += key;
output += "= ";
HexEncoder(new StringSink(output), false).Put(data, data.size());
output += "\n";
}
void OutputData(std::string &output, const std::string &key, const Integer &data)
{
SecByteBlock s(data.MinEncodedSize());
data.Encode(s, s.size());
OutputData(output, key, s);
}
void OutputData(std::string &output, DataType t, const std::string &data)
{
if (m_algorithm == "SKIPJACK")
{
if (m_test == "KAT")
{
if (t == OUTPUT)
output = m_line + data + "\n";
}
else
{
if (t != COUNT)
{
output += m_typeToName[t];
output += "=";
}
output += data;
output += t == OUTPUT ? "\n" : " ";
}
}
else if (m_algorithm == "TDES" && t == KEY_T && m_typeToName[KEY_T].empty())
{
output += "KEY1 = ";
output += data.substr(0, 16);
output += "\nKEY2 = ";
output += data.size() > 16 ? data.substr(16, 16) : data.substr(0, 16);
output += "\nKEY3 = ";
output += data.size() > 32 ? data.substr(32, 16) : data.substr(0, 16);
output += "\n";
}
else
{
output += m_typeToName[t];
output += " = ";
output += data;
output += "\n";
}
}
void OutputData(std::string &output, DataType t, int i)
{
OutputData(output, t, IntToString(i));
}
void OutputData(std::string &output, DataType t, const SecByteBlock &data)
{
std::string hexData;
StringSource(data.begin(), data.size(), true, new HexEncoder(new StringSink(hexData), false));
OutputData(output, t, hexData);
}
void OutputGivenData(std::string &output, DataType t, bool optional = false)
{
if (m_data.find(m_typeToName[t]) == m_data.end())
{
if (optional)
return;
throw Exception(Exception::OTHER_ERROR, "TestDataParser: key not found: " + m_typeToName[t]);
}
OutputData(output, t, m_data[m_typeToName[t]]);
}
template <class T>
BlockCipher * NewBT(T *)
{
if (!m_encrypt && (m_mode == "ECB" || m_mode == "CBC"))
return new typename T::Decryption;
else
return new typename T::Encryption;
}
template <class T>
SymmetricCipher * NewMode(T *, BlockCipher &bt, const byte *iv)
{
if (!m_encrypt)
return new typename T::Decryption(bt, iv, m_feedbackSize/8);
else
return new typename T::Encryption(bt, iv, m_feedbackSize/8);
}
static inline void Xor(SecByteBlock &z, const SecByteBlock &x, const SecByteBlock &y)
{
assert(x.size() == y.size());
z.resize(x.size());
xorbuf(z, x, y, x.size());
}
SecByteBlock UpdateKey(SecByteBlock key, const SecByteBlock *text)
{
unsigned int innerCount = (m_algorithm == "AES") ? 1000 : 10000;
int keySize = key.size(), blockSize = text[0].size();
SecByteBlock x(keySize);
for (int k=0; k<keySize;)
{
int pos = innerCount * blockSize - keySize + k;
memcpy(x + k, text[pos / blockSize] + pos % blockSize, blockSize - pos % blockSize);
k += blockSize - pos % blockSize;
}
if (m_algorithm == "TDES" || m_algorithm == "DES")
{
for (int i=0; i<keySize; i+=8)
{
xorbuf(key+i, x+keySize-8-i, 8);
DES::CorrectKeyParityBits(key+i);
}
}
else
xorbuf(key, x, keySize);
return key;
}
static inline void AssignLeftMostBits(SecByteBlock &z, const SecByteBlock &x, unsigned int K)
{
z.Assign(x, K/8);
}
virtual void DoTest()
{
std::string output;
if (m_algorithm == "DSS")
{
if (m_test == "sha")
{
assert(m_compactString.size() >= 2);
assert(m_compactString[0] == m_compactString.size()-2);
bool b = !!m_compactString[1];
Integer m;
unsigned int bitLength = 0;
for (unsigned int j = 2; j < m_compactString.size(); j++)
{
m <<= m_compactString[j];
for (unsigned int k = 0; k < m_compactString[j]; k++)
m.SetBit(k, b);
bitLength += m_compactString[j];
b = !b;
}
m_compactString.clear();
assert(bitLength % 8 == 0);
SecByteBlock message(bitLength / 8);
m.Encode(message, message.size());
SHA sha;
if (m_bracketString == "SHS Type 3 Strings")
{
SecByteBlock m1;
for (int j = 0; j < 100; j++)
{
for (word32 i = 1; i <= 50000; i++)
{
m1.resize(message.size() + j/4 + 3 + 4);
memcpy(m1, message, message.size());
memset(m1 + message.size(), 0, j/4 + 3);
PutWord(false, BIG_ENDIAN_ORDER, m1 + m1.size() - 4, i);
message.resize(sha.DigestSize());
sha.CalculateDigest(message, m1, m1.size());
}
StringSource(message, message.size(), true, new HexEncoder(new StringSink(output)));
output += " ^\n";
AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0);
}
}
else
{
StringSource(message, message.size(), true, new HashFilter(sha, new HexEncoder(new StringSink(output))));
output += " ^\n";
AttachedTransformation()->Put((byte *)output.data(), output.size());
}
}
else if (m_test == "prime")
{
Integer p((m_data["Prime"] + "h").c_str());
OutputData(output, "result", VerifyPrime(m_rng, p, 2) ? "P" : "F");
AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0);
}
else if (m_test == "pqg")
{
int n = atol(m_data["N"].c_str());
for (int i=0; i<n; i++)
{
Integer p, q, h, g;
int counter;
SecByteBlock seed(SHA::DIGESTSIZE);
do
{
m_rng.GenerateBlock(seed, seed.size());
}
while (!DSA::GeneratePrimes(seed, seed.size()*8, counter, p, 1024, q));
h.Randomize(m_rng, 2, p-2);
g = a_exp_b_mod_c(h, (p-1)/q, p);
OutputData(output, "P", p);
OutputData(output, "Q", q);
OutputData(output, "G", g);
OutputData(output, "Seed", seed);
OutputData(output, "H", h);
OutputData(output, "c", counter);
AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0);
}
}
else if (m_test == "xy")
{
Integer p((m_data["P"] + "h").c_str());
Integer q((m_data["Q"] + "h").c_str());
Integer g((m_data["G"] + "h").c_str());
for (int i=0; i<10; i++)
{
DSA::Signer priv(m_rng, p, q, g);
DSA::Verifier pub(priv);
OutputData(output, "X", priv.GetKey().GetPrivateExponent());
OutputData(output, "Y", pub.GetKey().GetPublicElement());
AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0);
}
}
else if (m_test == "gensig")
{
Integer p((m_data["P"] + "h").c_str());
Integer q((m_data["Q"] + "h").c_str());
Integer g((m_data["G"] + "h").c_str());
Integer x((m_data["X"] + "h").c_str());
DSA::Signer signer(p, q, g, x);
SecByteBlock sig(signer.SignatureLength());
StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size()))));
OutputData(output, "Sig", sig);
AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0);
}
else if (m_test == "versig")
{
Integer p((m_data["P"] + "h").c_str());
Integer q((m_data["Q"] + "h").c_str());
Integer g((m_data["G"] + "h").c_str());
Integer y((m_data["Y"] + "h").c_str());
DSA::Verifier verifier(p, q, g, y);
HexDecoder filter(new SignatureVerificationFilter(verifier));
StringSource(m_data["Sig"], true, new Redirector(filter, false));
StringSource(m_data["Msg"], true, new Redirector(filter, false));
filter.MessageEnd();
byte b;
filter.Get(b);
OutputData(output, "result", b ? "P" : "F");
AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0);
}
else if (m_test == "verpqg")
{
Integer p((m_data["P"] + "h").c_str());
Integer q((m_data["Q"] + "h").c_str());
Integer g((m_data["G"] + "h").c_str());
Integer h((m_data["H"] + "h").c_str());
int c = atol(m_data["c"].c_str());
SecByteBlock seed(m_data["Seed"].size()/2);
StringSource(m_data["Seed"], true, new HexDecoder(new ArraySink(seed, seed.size())));
Integer p1, q1;
bool result = DSA::GeneratePrimes(seed, seed.size()*8, c, p1, 1024, q1, true);
result = result && (p1 == p && q1 == q);
result = result && g == a_exp_b_mod_c(h, (p-1)/q, p);
OutputData(output, "result", result ? "P" : "F");
AttachedTransformation()->Put((byte *)output.data(), output.size());
output.resize(0);
}
return;
}
SecByteBlock &key = m_data2[KEY_T];
if (m_algorithm == "TDES")
{
if (!m_data["KEY1"].empty())
{
const std::string keys[3] = {m_data["KEY1"], m_data["KEY2"], m_data["KEY3"]};
key.resize(24);
HexDecoder hexDec(new ArraySink(key, key.size()));
for (int i=0; i<3; i++)
hexDec.Put((byte *)keys[i].data(), keys[i].size());
if (keys[0] == keys[2])
{
if (keys[0] == keys[1])
key.resize(8);
else
key.resize(16);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -