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