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 10NAMESPACE_BEGIN(CryptoPP) 11 12template <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 26template <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 42template <class T> void DL_FixedBasePrecomputationImpl<T>::Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &bt) 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 57template <class T> void DL_FixedBasePrecomputationImpl<T>::Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &bt) const 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 67template <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 90template <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 98template <class T> T 99 DL_FixedBasePrecomputationImpl<T>::CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, 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 110NAMESPACE_END 111 112#endif 113