Crypto++
eprecomp.cpp
1 // eprecomp.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 
5 #ifndef CRYPTOPP_IMPORTS
6 
7 #include "eprecomp.h"
8 #include "asn.h"
9 
10 NAMESPACE_BEGIN(CryptoPP)
11 
12 template <class T> void DL_FixedBasePrecomputationImpl<T>::SetBase(const DL_GroupPrecomputation<Element> &group, const Element &i_base)
13 {
14  m_base = group.NeedConversions() ? group.ConvertIn(i_base) : i_base;
15 
16  if (m_bases.empty() || !(m_base == m_bases[0]))
17  {
18  m_bases.resize(1);
19  m_bases[0] = m_base;
20  }
21 
22  if (group.NeedConversions())
23  m_base = i_base;
24 }
25 
26 template <class T> void DL_FixedBasePrecomputationImpl<T>::Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage)
27 {
28  assert(m_bases.size() > 0);
29  assert(storage <= maxExpBits);
30 
31  if (storage > 1)
32  {
33  m_windowSize = (maxExpBits+storage-1)/storage;
34  m_exponentBase = Integer::Power2(m_windowSize);
35  }
36 
37  m_bases.resize(storage);
38  for (unsigned i=1; i<storage; i++)
39  m_bases[i] = group.GetGroup().ScalarMultiply(m_bases[i-1], m_exponentBase);
40 }
41 
43 {
44  BERSequenceDecoder seq(bt);
45  word32 version;
46  BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1);
47  m_exponentBase.BERDecode(seq);
48  m_windowSize = m_exponentBase.BitCount() - 1;
49  m_bases.clear();
50  while (!seq.EndReached())
51  m_bases.push_back(group.BERDecodeElement(seq));
52  if (!m_bases.empty() && group.NeedConversions())
53  m_base = group.ConvertOut(m_bases[0]);
54  seq.MessageEnd();
55 }
56 
58 {
59  DERSequenceEncoder seq(bt);
60  DEREncodeUnsigned<word32>(seq, 1); // version
61  m_exponentBase.DEREncode(seq);
62  for (unsigned i=0; i<m_bases.size(); i++)
63  group.DEREncodeElement(seq, m_bases[i]);
64  seq.MessageEnd();
65 }
66 
67 template <class T> void DL_FixedBasePrecomputationImpl<T>::PrepareCascade(const DL_GroupPrecomputation<Element> &i_group, std::vector<BaseAndExponent<Element> > &eb, const Integer &exponent) const
68 {
69  const AbstractGroup<T> &group = i_group.GetGroup();
70 
71  Integer r, q, e = exponent;
72  bool fastNegate = group.InversionIsFast() && m_windowSize > 1;
73  unsigned int i;
74 
75  for (i=0; i+1<m_bases.size(); i++)
76  {
77  Integer::DivideByPowerOf2(r, q, e, m_windowSize);
78  std::swap(q, e);
79  if (fastNegate && r.GetBit(m_windowSize-1))
80  {
81  ++e;
82  eb.push_back(BaseAndExponent<Element>(group.Inverse(m_bases[i]), m_exponentBase - r));
83  }
84  else
85  eb.push_back(BaseAndExponent<Element>(m_bases[i], r));
86  }
87  eb.push_back(BaseAndExponent<Element>(m_bases[i], e));
88 }
89 
90 template <class T> T DL_FixedBasePrecomputationImpl<T>::Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const
91 {
92  std::vector<BaseAndExponent<Element> > eb; // array of segments of the exponent and precalculated bases
93  eb.reserve(m_bases.size());
94  PrepareCascade(group, eb, exponent);
95  return group.ConvertOut(GeneralCascadeMultiplication<Element>(group.GetGroup(), eb.begin(), eb.end()));
96 }
97 
98 template <class T> T
100  const DL_FixedBasePrecomputation<T> &i_pc2, const Integer &exponent2) const
101 {
102  std::vector<BaseAndExponent<Element> > eb; // array of segments of the exponent and precalculated bases
103  const DL_FixedBasePrecomputationImpl<T> &pc2 = static_cast<const DL_FixedBasePrecomputationImpl<T> &>(i_pc2);
104  eb.reserve(m_bases.size() + pc2.m_bases.size());
105  PrepareCascade(group, eb, exponent);
106  pc2.PrepareCascade(group, eb, exponent2);
107  return group.ConvertOut(GeneralCascadeMultiplication<Element>(group.GetGroup(), eb.begin(), eb.end()));
108 }
109 
110 NAMESPACE_END
111 
112 #endif