/* Copyright (c) 1999-2000 Redshift Software, Inc. All Rights Reserved. */ #include #include #include #include #include #include #include #include #include com_redshift_software_libraries_algorithm_p { using namespace Botan; namespace { std::string encode(UInt8 * d, UInt32 s) { UInt32 size = s; UInt32 total = s+4; byteswap(size); std::string result; boost::scoped_array buffer(new UInt8[total]); std::memcpy(buffer.get(),&size,4); std::memcpy(buffer.get()+4,d,s); byte output[5]; output[4] = 0; UInt32 i; for (i = 0; i < total-3; i += 3) { Botan::Base64_Encoder::encode(buffer.get()+i,output); result += (char*)output; } { byte in[3]; in[0] = i < total ? buffer.get()[i++] : '\0'; in[1] = i < total ? buffer.get()[i++] : '\0'; in[2] = i < total ? buffer.get()[i++] : '\0'; Botan::Base64_Encoder::encode(in,output); result += (char*)output; } return result; } Pointer decode(const char * source, UInt32 source_size, UInt32 & aSize) { UInt32 s = (source_size/4)*3; boost::scoped_array d(new UInt8[s]); UInt i = 0; UInt j = 0; while (i < source_size) { Botan::Base64_Decoder::decode((Botan::byte*)(source+i),d.get()+j); i += 4; j += 3; } UInt32 size; std::memcpy(&size,d.get(),4); byteswap(size); aSize = size; Pointer result = new UInt8[size]; std::memcpy(result,d.get()+4,size); return result; } } struct OneWayValue::Data { BigInt mValue; }; OneWayValue::OneWayValue() : mSize(0) , mData(kNull) { Botan::initialize(); mData = AutoPointer(new Data); } OneWayValue::OneWayValue(Pointer aValue,UInt aSize) : mSize(aSize) , mData(kNull) { Botan::initialize(); mData = AutoPointer(new Data); set(aValue,aSize); } OneWayValue::OneWayValue(OneWayValue const & aValue) : mSize(aValue.mSize) , mData(new Data) { Botan::initialize(); mData->mValue = aValue.mData->mValue; } OneWayValue & OneWayValue::operator =(OneWayValue const & aValue) { mData->mValue = aValue.mData->mValue; mSize = aValue.mSize; return *this; } OneWayValue::~OneWayValue() { } UInt OneWayValue::getSize() { return mSize; } void OneWayValue::setSize(UInt aSize) { mSize = aSize; } std::wstring OneWayValue::getString() { std::wstring result(L""); if (mSize > 0) { Pointer bytes = getBytes(); std::string temp1(""); temp1 = encode((UInt8*)bytes,mSize); UString temp2((const char*)temp1.c_str()); result += (const wchar_t*)temp2; delete [] reinterpret_cast(bytes); } return result; } std::string OneWayValue::getAsciiString() { std::string result(""); if (mSize > 0) { Pointer bytes = getBytes(); result = encode((UInt8*)bytes,mSize); delete [] reinterpret_cast(bytes); } return result; } com::redshift_software::UString OneWayValue::getUString() { com::redshift_software::UString result; if (mSize > 0) { Pointer bytes = getBytes(); std::string temp = encode((UInt8*)bytes,mSize); result = UString(temp.c_str()); delete [] reinterpret_cast(bytes); } return result; } Pointer OneWayValue::getBytes() { Pointer result= kNull; if (mSize > 0) { result = new UInt8[mSize]; Botan::SecureVector buffer(BigInt::encode(mData->mValue)); std::memcpy(result,buffer.begin(),mSize); } return result; } void OneWayValue::set(Pointer aValue,UInt aSize) { mSize = aSize; if (aSize > 0) { const Botan::SecureVector buffer((const Botan::byte*)aValue,aSize); mData->mValue = BigInt::decode(buffer); } } void OneWayValue::set(const std::wstring & aValue) { UString temp1(aValue.c_str()); std::string temp2 = (const char*)temp1; set(temp2.c_str()); } void OneWayValue::set(const std::string & aValue) { set(aValue.c_str()); } void OneWayValue::set(const UString & aValue) { set((const char *)aValue); } void OneWayValue::set(const char * aValue) { if (std::strlen(aValue) > 0) { UInt32 size = 0; Pointer temp2 = decode(aValue,std::strlen(aValue),size); set(temp2,size); delete [] reinterpret_cast(temp2); } } OneWayValue::Data & OneWayValue::getData() { return (*mData.get()); } struct OneWayAccumulator::Data { BigInt mModulusP; BigInt mModulusQ; BigInt mModulus; BigInt mInitial; AutoPointer mModulusReducer; AutoPointer mPhiReducer; BigInt mAccumulation; AutoPointer mFixedAccumulation; }; OneWayAccumulator::OneWayAccumulator() : mModulusSet(false) , mInitialSet(false) { Botan::initialize(); mData = AutoPointer(new Data); } OneWayAccumulator::~OneWayAccumulator() { } bool OneWayAccumulator::generateModulus(UInt32 aSize) { mData->mModulusP = random_safe_prime(aSize*4); mData->mModulusQ = random_safe_prime(aSize*4); mData->mInitial = random_prime((aSize*4)-1); mData->mModulus = mData->mModulusP; mData->mModulus *= mData->mModulusQ; mData->mModulusReducer.reset(new BarrettReducer(mData->mModulus)); BigInt phi = mData->mModulusP-1; phi *= mData->mModulusQ-1; mData->mPhiReducer.reset(new BarrettReducer(phi)); mData->mFixedAccumulation.reset(new FixedBase_Exp(mData->mInitial,phi)); mModulusSet = true; mInitialSet = true; return true; } bool OneWayAccumulator::setModulus(OneWayValue & aP, OneWayValue & aQ) { mData->mModulusP = aP.getData().mValue; mData->mModulusQ = aQ.getData().mValue; mData->mModulus = mData->mModulusP; mData->mModulus *= mData->mModulusQ; mData->mModulusReducer.reset(new BarrettReducer(mData->mModulus)); BigInt phi = mData->mModulusP-1; phi *= mData->mModulusQ-1; mData->mPhiReducer.reset(new BarrettReducer(phi)); if (mInitialSet) mData->mFixedAccumulation.reset( new FixedBase_Exp(mData->mInitial,mData->mModulus)); else mData->mFixedAccumulation.reset(kNull); mModulusSet = true; return true; } bool OneWayAccumulator::setModulus(OneWayValue & aM) { mData->mModulus = aM.getData().mValue; mData->mModulusReducer.reset(new BarrettReducer(mData->mModulus)); mModulusSet = true; return true; } OneWayValue OneWayAccumulator::getModulusP() { OneWayValue result; if (mModulusSet) { result.getData().mValue = mData->mModulusP; result.setSize(mData->mModulusP.bytes()); } return result; } OneWayValue OneWayAccumulator::getModulusQ() { OneWayValue result; if (mModulusSet) { result.getData().mValue = mData->mModulusQ; result.setSize(mData->mModulusQ.bytes()); } return result; } OneWayValue OneWayAccumulator::getModulus() { OneWayValue result; if (mModulusSet) { result.getData().mValue = mData->mModulus; result.setSize(mData->mModulus.bytes()); } return result; } void OneWayAccumulator::setAccumulation(OneWayValue & aAccumulation) { mData->mAccumulation = aAccumulation.getData().mValue; } OneWayValue OneWayAccumulator::getInitial() { OneWayValue result; if (mInitialSet) { result.getData().mValue = mData->mInitial; result.setSize(mData->mInitial.bytes()); } return result; } bool OneWayAccumulator::setInitial(OneWayValue & aInitial) { mData->mInitial = aInitial.getData().mValue; if (mModulusSet) mData->mFixedAccumulation.reset( new FixedBase_Exp(mData->mInitial,mData->mModulusReducer->get_modulus())); else mData->mFixedAccumulation.reset(kNull); mInitialSet = true; return true; } bool OneWayAccumulator::verify(OneWayValue & aPartialAccumulation, OneWayValue & aMember) { BigInt accumulation = accumulate(aPartialAccumulation,aMember).getData().mValue; return mData->mAccumulation == accumulation; } OneWayValue OneWayAccumulator::residue(OneWayValue & aX) { OneWayValue result; result.getData().mValue =mData->mPhiReducer->reduce(aX.getData().mValue); result.setSize(result.getData().mValue.bytes()); return result; } OneWayValue OneWayAccumulator::residue(OneWayValue & aU, OneWayValue & aW) { OneWayValue result; result.getData().mValue = mData->mPhiReducer->multiply(aU.getData().mValue,aW.getData().mValue); result.setSize(result.getData().mValue.bytes()); return result; } OneWayValue OneWayAccumulator::accumulate(OneWayValue & aBase, OneWayValue & aResidue) { OneWayValue result; if (mModulusSet) { result.getData().mValue = power_mod(aBase.getData().mValue,aResidue.getData().mValue,mData->mModulusReducer.get()); result.setSize(result.getData().mValue.bytes()); } return result; } OneWayValue OneWayAccumulator::accumulate(OneWayValue & aResidue) { OneWayValue result; bool doAccumulate = mModulusSet && mInitialSet && mData->mFixedAccumulation.get() != kNull; if (doAccumulate) { result.getData().mValue =mData->mFixedAccumulation->power_mod(aResidue.getData().mValue); result.setSize(result.getData().mValue.bytes()); } return result; } } p_com_redshift_software_libraries_algorithm