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