1// dsa.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4
5#ifndef CRYPTOPP_IMPORTS
6
7#include "dsa.h"
8#include "nbtheory.h"
9
10NAMESPACE_BEGIN(CryptoPP)
11
12size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat, const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat)
13{
14	Integer r, s;
15	StringStore store(signature, signatureLen);
16	ArraySink sink(buffer, bufferSize);
17
18	switch (fromFormat)
19	{
20	case DSA_P1363:
21		r.Decode(store, signatureLen/2);
22		s.Decode(store, signatureLen/2);
23		break;
24	case DSA_DER:
25	{
26		BERSequenceDecoder seq(store);
27		r.BERDecode(seq);
28		s.BERDecode(seq);
29		seq.MessageEnd();
30		break;
31	}
32	case DSA_OPENPGP:
33		r.OpenPGPDecode(store);
34		s.OpenPGPDecode(store);
35		break;
36	}
37
38	switch (toFormat)
39	{
40	case DSA_P1363:
41		r.Encode(sink, bufferSize/2);
42		s.Encode(sink, bufferSize/2);
43		break;
44	case DSA_DER:
45	{
46		DERSequenceEncoder seq(sink);
47		r.DEREncode(seq);
48		s.DEREncode(seq);
49		seq.MessageEnd();
50		break;
51	}
52	case DSA_OPENPGP:
53		r.OpenPGPEncode(sink);
54		s.OpenPGPEncode(sink);
55		break;
56	}
57
58	return (size_t)sink.TotalPutLength();
59}
60
61bool DSA::GeneratePrimes(const byte *seedIn, unsigned int g, int &counter,
62						  Integer &p, unsigned int L, Integer &q, bool useInputCounterValue)
63{
64	assert(g%8 == 0);
65
66	SHA sha;
67	SecByteBlock seed(seedIn, g/8);
68	SecByteBlock U(SHA::DIGESTSIZE);
69	SecByteBlock temp(SHA::DIGESTSIZE);
70	SecByteBlock W(((L-1)/160+1) * SHA::DIGESTSIZE);
71	const int n = (L-1) / 160;
72	const int b = (L-1) % 160;
73	Integer X;
74
75	sha.CalculateDigest(U, seed, g/8);
76
77	for (int i=g/8-1, carry=true; i>=0 && carry; i--)
78		carry=!++seed[i];
79
80	sha.CalculateDigest(temp, seed, g/8);
81	xorbuf(U, temp, SHA::DIGESTSIZE);
82
83	U[0] |= 0x80;
84	U[SHA::DIGESTSIZE-1] |= 1;
85	q.Decode(U, SHA::DIGESTSIZE);
86
87	if (!IsPrime(q))
88		return false;
89
90	int counterEnd = useInputCounterValue ? counter+1 : 4096;
91
92	for (int c = 0; c < counterEnd; c++)
93	{
94		for (int k=0; k<=n; k++)
95		{
96			for (int i=g/8-1, carry=true; i>=0 && carry; i--)
97				carry=!++seed[i];
98			if (!useInputCounterValue || c == counter)
99				sha.CalculateDigest(W+(n-k)*SHA::DIGESTSIZE, seed, g/8);
100		}
101		if (!useInputCounterValue || c == counter)
102		{
103			W[SHA::DIGESTSIZE - 1 - b/8] |= 0x80;
104			X.Decode(W + SHA::DIGESTSIZE - 1 - b/8, L/8);
105			p = X-((X % (2*q))-1);
106
107			if (p.GetBit(L-1) && IsPrime(p))
108			{
109				counter = c;
110				return true;
111			}
112		}
113	}
114	return false;
115}
116
117NAMESPACE_END
118
119#endif
120