/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /* based on Wei Dai's algebra.cpp from CryptoPP */ #undef NDEBUG #define DEBUG // GCC 4.0 bug if NDEBUG and Optimize > 1 #include "runtime.hpp" #include "algebra.hpp" #ifdef USE_SYS_STL #include #else #include "vector.hpp" #endif namespace STL = STL_NAMESPACE; namespace TaoCrypt { const Integer& AbstractGroup::Double(const Element &a) const { return Add(a, a); } const Integer& AbstractGroup::Subtract(const Element &a, const Element &b) const { // make copy of a in case Inverse() overwrites it Element a1(a); return Add(a1, Inverse(b)); } Integer& AbstractGroup::Accumulate(Element &a, const Element &b) const { return a = Add(a, b); } Integer& AbstractGroup::Reduce(Element &a, const Element &b) const { return a = Subtract(a, b); } const Integer& AbstractRing::Square(const Element &a) const { return Multiply(a, a); } const Integer& AbstractRing::Divide(const Element &a, const Element &b) const { // make copy of a in case MultiplicativeInverse() overwrites it Element a1(a); return Multiply(a1, MultiplicativeInverse(b)); } const Integer& AbstractEuclideanDomain::Mod(const Element &a, const Element &b) const { Element q; DivisionAlgorithm(result, q, a, b); return result; } const Integer& AbstractEuclideanDomain::Gcd(const Element &a, const Element &b) const { STL::vector g(3); g[0]= b; g[1]= a; unsigned int i0=0, i1=1, i2=2; while (!Equal(g[i1], this->Identity())) { g[i2] = Mod(g[i0], g[i1]); unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; } return result = g[i0]; } Integer AbstractGroup::ScalarMultiply(const Element &base, const Integer &exponent) const { Element result; SimultaneousMultiply(&result, base, &exponent, 1); return result; } Integer AbstractGroup::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const { const unsigned expLen = max(e1.BitCount(), e2.BitCount()); if (expLen==0) return Identity(); const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3)); const unsigned tableSize = 1< powerTable(tableSize << w); powerTable[1] = x; powerTable[tableSize] = y; if (w==1) powerTable[3] = Add(x,y); else { powerTable[2] = Double(x); powerTable[2*tableSize] = Double(y); unsigned i, j; for (i=3; i=0; i--) { power1 = 2*power1 + e1.GetBit(i); power2 = 2*power2 + e2.GetBit(i); if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize) { unsigned squaresBefore = prevPosition-i; unsigned squaresAfter = 0; prevPosition = i; while ((power1 || power2) && power1%2 == 0 && power2%2==0) { power1 /= 2; power2 /= 2; squaresBefore--; squaresAfter++; } if (firstTime) { result = powerTable[(power2<= expLen) { finished = true; return; } skipCount++; } exp >>= skipCount; windowBegin += skipCount; expWindow = exp % (1 << windowSize); if (fastNegate && exp.GetBit(windowSize)) { negateNext = true; expWindow = (1 << windowSize) - expWindow; exp += windowModulus; } else negateNext = false; } Integer exp, windowModulus; unsigned int windowSize, windowBegin, expWindow; bool fastNegate, negateNext, firstTime, finished; }; void AbstractGroup::SimultaneousMultiply(Integer *results, const Integer &base, const Integer *expBegin, unsigned int expCount) const { STL::vector > buckets(expCount); STL::vector exponents; exponents.reserve(expCount); unsigned int i; for (i=0; i 1) { for (size_t j = buckets[i].size()-2; j >= 1; j--) { Accumulate(buckets[i][j], buckets[i][j+1]); Accumulate(r, buckets[i][j]); } Accumulate(buckets[i][0], buckets[i][1]); r = Add(Double(r), buckets[i][0]); } } } Integer AbstractRing::Exponentiate(const Element &base, const Integer &exponent) const { Element result; SimultaneousExponentiate(&result, base, &exponent, 1); return result; } Integer AbstractRing::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const { return MultiplicativeGroup().AbstractGroup::CascadeScalarMultiply( x, e1, y, e2); } void AbstractRing::SimultaneousExponentiate(Integer *results, const Integer &base, const Integer *exponents, unsigned int expCount) const { MultiplicativeGroup().AbstractGroup::SimultaneousMultiply(results, base, exponents, expCount); } } // namespace #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION namespace mySTL { template TaoCrypt::WindowSlider* uninit_copy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); template void destroy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); template TaoCrypt::WindowSlider* GetArrayMemory(size_t); template void FreeArrayMemory(TaoCrypt::WindowSlider*); } #endif