|
|
|
// dsa.cpp - written and placed in the public domain by Wei Dai
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
|
|
|
|
#ifndef CRYPTOPP_IMPORTS
|
|
|
|
|
|
|
|
#include "dsa.h"
|
|
|
|
#include "nbtheory.h"
|
|
|
|
|
|
|
|
NAMESPACE_BEGIN(CryptoPP)
|
|
|
|
|
|
|
|
size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat, const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat)
|
|
|
|
{
|
|
|
|
Integer r, s;
|
|
|
|
StringStore store(signature, signatureLen);
|
|
|
|
ArraySink sink(buffer, bufferSize);
|
|
|
|
|
|
|
|
switch (fromFormat)
|
|
|
|
{
|
|
|
|
case DSA_P1363:
|
|
|
|
r.Decode(store, signatureLen/2);
|
|
|
|
s.Decode(store, signatureLen/2);
|
|
|
|
break;
|
|
|
|
case DSA_DER:
|
|
|
|
{
|
|
|
|
BERSequenceDecoder seq(store);
|
|
|
|
r.BERDecode(seq);
|
|
|
|
s.BERDecode(seq);
|
|
|
|
seq.MessageEnd();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DSA_OPENPGP:
|
|
|
|
r.OpenPGPDecode(store);
|
|
|
|
s.OpenPGPDecode(store);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (toFormat)
|
|
|
|
{
|
|
|
|
case DSA_P1363:
|
|
|
|
r.Encode(sink, bufferSize/2);
|
|
|
|
s.Encode(sink, bufferSize/2);
|
|
|
|
break;
|
|
|
|
case DSA_DER:
|
|
|
|
{
|
|
|
|
DERSequenceEncoder seq(sink);
|
|
|
|
r.DEREncode(seq);
|
|
|
|
s.DEREncode(seq);
|
|
|
|
seq.MessageEnd();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DSA_OPENPGP:
|
|
|
|
r.OpenPGPEncode(sink);
|
|
|
|
s.OpenPGPEncode(sink);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (size_t)sink.TotalPutLength();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DSA::GeneratePrimes(const byte *seedIn, unsigned int g, int &counter,
|
|
|
|
Integer &p, unsigned int L, Integer &q, bool useInputCounterValue)
|
|
|
|
{
|
|
|
|
assert(g%8 == 0);
|
|
|
|
|
|
|
|
SHA sha;
|
|
|
|
SecByteBlock seed(seedIn, g/8);
|
|
|
|
SecByteBlock U(SHA::DIGESTSIZE);
|
|
|
|
SecByteBlock temp(SHA::DIGESTSIZE);
|
|
|
|
SecByteBlock W(((L-1)/160+1) * SHA::DIGESTSIZE);
|
|
|
|
const int n = (L-1) / 160;
|
|
|
|
const int b = (L-1) % 160;
|
|
|
|
Integer X;
|
|
|
|
|
|
|
|
sha.CalculateDigest(U, seed, g/8);
|
|
|
|
|
|
|
|
for (int i=g/8-1, carry=true; i>=0 && carry; i--)
|
|
|
|
carry=!++seed[i];
|
|
|
|
|
|
|
|
sha.CalculateDigest(temp, seed, g/8);
|
|
|
|
xorbuf(U, temp, SHA::DIGESTSIZE);
|
|
|
|
|
|
|
|
U[0] |= 0x80;
|
|
|
|
U[SHA::DIGESTSIZE-1] |= 1;
|
|
|
|
q.Decode(U, SHA::DIGESTSIZE);
|
|
|
|
|
|
|
|
if (!IsPrime(q))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
int counterEnd = useInputCounterValue ? counter+1 : 4096;
|
|
|
|
|
|
|
|
for (int c = 0; c < counterEnd; c++)
|
|
|
|
{
|
|
|
|
for (int k=0; k<=n; k++)
|
|
|
|
{
|
|
|
|
for (int i=g/8-1, carry=true; i>=0 && carry; i--)
|
|
|
|
carry=!++seed[i];
|
|
|
|
if (!useInputCounterValue || c == counter)
|
|
|
|
sha.CalculateDigest(W+(n-k)*SHA::DIGESTSIZE, seed, g/8);
|
|
|
|
}
|
|
|
|
if (!useInputCounterValue || c == counter)
|
|
|
|
{
|
|
|
|
W[SHA::DIGESTSIZE - 1 - b/8] |= 0x80;
|
|
|
|
X.Decode(W + SHA::DIGESTSIZE - 1 - b/8, L/8);
|
|
|
|
p = X-((X % (2*q))-1);
|
|
|
|
|
|
|
|
if (p.GetBit(L-1) && IsPrime(p))
|
|
|
|
{
|
|
|
|
counter = c;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
NAMESPACE_END
|
|
|
|
|
|
|
|
#endif
|