summaryrefslogtreecommitdiff
path: root/src-cryptopp/gfpcrypt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-cryptopp/gfpcrypt.cpp')
-rw-r--r--src-cryptopp/gfpcrypt.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/src-cryptopp/gfpcrypt.cpp b/src-cryptopp/gfpcrypt.cpp
new file mode 100644
index 0000000..6d9ffce
--- /dev/null
+++ b/src-cryptopp/gfpcrypt.cpp
@@ -0,0 +1,275 @@
+// dsa.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "gfpcrypt.h"
+#include "asn.h"
+#include "oids.h"
+#include "nbtheory.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void TestInstantiations_gfpcrypt()
+{
+ GDSA<SHA>::Signer test;
+ GDSA<SHA>::Verifier test1;
+ DSA::Signer test5(NullRNG(), 100);
+ DSA::Signer test2(test5);
+ NR<SHA>::Signer test3;
+ NR<SHA>::Verifier test4;
+ DLIES<>::Encryptor test6;
+ DLIES<>::Decryptor test7;
+}
+
+void DL_GroupParameters_DSA::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
+{
+ Integer p, q, g;
+
+ if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g))
+ {
+ q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2);
+ }
+ else
+ {
+ int modulusSize = 1024;
+ alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
+
+ if (!DSA::IsValidPrimeLength(modulusSize))
+ throw InvalidArgument("DSA: not a valid prime length");
+
+ SecByteBlock seed(SHA::DIGESTSIZE);
+ Integer h;
+ int c;
+
+ do
+ {
+ rng.GenerateBlock(seed, SHA::DIGESTSIZE);
+ } while (!DSA::GeneratePrimes(seed, SHA::DIGESTSIZE*8, c, p, modulusSize, q));
+
+ do
+ {
+ h.Randomize(rng, 2, p-2);
+ g = a_exp_b_mod_c(h, (p-1)/q, p);
+ } while (g <= 1);
+ }
+
+ Initialize(p, q, g);
+}
+
+bool DL_GroupParameters_DSA::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = DL_GroupParameters_GFP::ValidateGroup(rng, level);
+ pass = pass && DSA::IsValidPrimeLength(GetModulus().BitCount());
+ pass = pass && GetSubgroupOrder().BitCount() == 160;
+ return pass;
+}
+
+void DL_SignatureMessageEncodingMethod_DSA::ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+{
+ assert(recoverableMessageLength == 0);
+ assert(hashIdentifier.second == 0);
+ const size_t representativeByteLength = BitsToBytes(representativeBitLength);
+ const size_t digestSize = hash.DigestSize();
+ const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize);
+
+ memset(representative, 0, paddingLength);
+ hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize));
+
+ if (digestSize*8 > representativeBitLength)
+ {
+ Integer h(representative, representativeByteLength);
+ h >>= representativeByteLength*8 - representativeBitLength;
+ h.Encode(representative, representativeByteLength);
+ }
+}
+
+void DL_SignatureMessageEncodingMethod_NR::ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+{
+ assert(recoverableMessageLength == 0);
+ assert(hashIdentifier.second == 0);
+ const size_t representativeByteLength = BitsToBytes(representativeBitLength);
+ const size_t digestSize = hash.DigestSize();
+ const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize);
+
+ memset(representative, 0, paddingLength);
+ hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize));
+
+ if (digestSize*8 >= representativeBitLength)
+ {
+ Integer h(representative, representativeByteLength);
+ h >>= representativeByteLength*8 - representativeBitLength + 1;
+ h.Encode(representative, representativeByteLength);
+ }
+}
+
+bool DL_GroupParameters_IntegerBased::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
+{
+ const Integer &p = GetModulus(), &q = GetSubgroupOrder();
+
+ bool pass = true;
+ pass = pass && p > Integer::One() && p.IsOdd();
+ pass = pass && q > Integer::One() && q.IsOdd();
+
+ if (level >= 1)
+ pass = pass && GetCofactor() > Integer::One() && GetGroupOrder() % q == Integer::Zero();
+ if (level >= 2)
+ pass = pass && VerifyPrime(rng, q, level-2) && VerifyPrime(rng, p, level-2);
+
+ return pass;
+}
+
+bool DL_GroupParameters_IntegerBased::ValidateElement(unsigned int level, const Integer &g, const DL_FixedBasePrecomputation<Integer> *gpc) const
+{
+ const Integer &p = GetModulus(), &q = GetSubgroupOrder();
+
+ bool pass = true;
+ pass = pass && GetFieldType() == 1 ? g.IsPositive() : g.NotNegative();
+ pass = pass && g < p && !IsIdentity(g);
+
+ if (level >= 1)
+ {
+ if (gpc)
+ pass = pass && gpc->Exponentiate(GetGroupPrecomputation(), Integer::One()) == g;
+ }
+ if (level >= 2)
+ {
+ if (GetFieldType() == 2)
+ pass = pass && Jacobi(g*g-4, p)==-1;
+
+ // verifying that Lucas((p+1)/2, w, p)==2 is omitted because it's too costly
+ // and at most 1 bit is leaked if it's false
+ bool fullValidate = (GetFieldType() == 2 && level >= 3) || !FastSubgroupCheckAvailable();
+
+ if (fullValidate && pass)
+ {
+ Integer gp = gpc ? gpc->Exponentiate(GetGroupPrecomputation(), q) : ExponentiateElement(g, q);
+ pass = pass && IsIdentity(gp);
+ }
+ else if (GetFieldType() == 1)
+ pass = pass && Jacobi(g, p) == 1;
+ }
+
+ return pass;
+}
+
+void DL_GroupParameters_IntegerBased::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
+{
+ Integer p, q, g;
+
+ if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g))
+ {
+ q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2);
+ }
+ else
+ {
+ int modulusSize, subgroupOrderSize;
+
+ if (!alg.GetIntValue("ModulusSize", modulusSize))
+ modulusSize = alg.GetIntValueWithDefault("KeySize", 2048);
+
+ if (!alg.GetIntValue("SubgroupOrderSize", subgroupOrderSize))
+ subgroupOrderSize = GetDefaultSubgroupOrderSize(modulusSize);
+
+ PrimeAndGenerator pg;
+ pg.Generate(GetFieldType() == 1 ? 1 : -1, rng, modulusSize, subgroupOrderSize);
+ p = pg.Prime();
+ q = pg.SubPrime();
+ g = pg.Generator();
+ }
+
+ Initialize(p, q, g);
+}
+
+Integer DL_GroupParameters_IntegerBased::DecodeElement(const byte *encoded, bool checkForGroupMembership) const
+{
+ Integer g(encoded, GetModulus().ByteCount());
+ if (!ValidateElement(1, g, NULL))
+ throw DL_BadElement();
+ return g;
+}
+
+void DL_GroupParameters_IntegerBased::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder parameters(bt);
+ Integer p(parameters);
+ Integer q(parameters);
+ Integer g;
+ if (parameters.EndReached())
+ {
+ g = q;
+ q = ComputeGroupOrder(p) / 2;
+ }
+ else
+ g.BERDecode(parameters);
+ parameters.MessageEnd();
+
+ SetModulusAndSubgroupGenerator(p, g);
+ SetSubgroupOrder(q);
+}
+
+void DL_GroupParameters_IntegerBased::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder parameters(bt);
+ GetModulus().DEREncode(parameters);
+ m_q.DEREncode(parameters);
+ GetSubgroupGenerator().DEREncode(parameters);
+ parameters.MessageEnd();
+}
+
+bool DL_GroupParameters_IntegerBased::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper<DL_GroupParameters<Element> >(this, name, valueType, pValue)
+ CRYPTOPP_GET_FUNCTION_ENTRY(Modulus);
+}
+
+void DL_GroupParameters_IntegerBased::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY2(Modulus, SubgroupGenerator)
+ CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder)
+ ;
+}
+
+OID DL_GroupParameters_IntegerBased::GetAlgorithmID() const
+{
+ return ASN1::id_dsa();
+}
+
+void DL_GroupParameters_GFP::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
+{
+ ModularArithmetic ma(GetModulus());
+ ma.SimultaneousExponentiate(results, base, exponents, exponentsCount);
+}
+
+DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::MultiplyElements(const Element &a, const Element &b) const
+{
+ return a_times_b_mod_c(a, b, GetModulus());
+}
+
+DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const
+{
+ ModularArithmetic ma(GetModulus());
+ return ma.CascadeExponentiate(element1, exponent1, element2, exponent2);
+}
+
+Integer DL_GroupParameters_IntegerBased::GetMaxExponent() const
+{
+ return STDMIN(GetSubgroupOrder()-1, Integer::Power2(2*DiscreteLogWorkFactor(GetFieldType()*GetModulus().BitCount())));
+}
+
+unsigned int DL_GroupParameters_IntegerBased::GetDefaultSubgroupOrderSize(unsigned int modulusSize) const
+{
+ return 2*DiscreteLogWorkFactor(GetFieldType()*modulusSize);
+}
+
+NAMESPACE_END
+
+#endif