Crypto++
dsa.cpp
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 
10 NAMESPACE_BEGIN(CryptoPP)
11 
12 size_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 
61 bool 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 
117 NAMESPACE_END
118 
119 #endif