Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ida.cpp

00001 // ida.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "ida.h"
00005 
00006 #include "algebra.h"
00007 #include "gf2_32.h"
00008 #include "polynomi.h"
00009 
00010 #include "polynomi.cpp"
00011 
00012 ANONYMOUS_NAMESPACE_BEGIN
00013 static const CryptoPP::GF2_32 field;
00014 NAMESPACE_END
00015 
00016 using namespace std;
00017 
00018 NAMESPACE_BEGIN(CryptoPP)
00019 
00020 RawIDA::RawIDA(unsigned int threshold, BufferedTransformation *outQueue)
00021         : Filter(outQueue), m_lastMapPosition(m_inputChannelMap.end()), m_threshold(threshold), m_channelsReady(0), m_channelsFinished(0)
00022         , m_w(threshold), m_y(threshold)
00023 {
00024         assert(threshold > 0);
00025         m_inputQueues.reserve(threshold);
00026 }
00027 
00028 unsigned int RawIDA::InsertInputChannel(word32 channelId)
00029 {
00030         if (m_lastMapPosition != m_inputChannelMap.end())
00031         {
00032                 if (m_lastMapPosition->first == channelId)
00033                         goto skipFind;
00034                 ++m_lastMapPosition;
00035                 if (m_lastMapPosition != m_inputChannelMap.end() && m_lastMapPosition->first == channelId)
00036                         goto skipFind;
00037         }
00038         m_lastMapPosition = m_inputChannelMap.find(channelId);
00039 
00040 skipFind:
00041         if (m_lastMapPosition == m_inputChannelMap.end())
00042         {
00043                 if (m_inputChannelIds.size() == m_threshold)
00044                         return m_threshold;
00045 
00046                 m_lastMapPosition = m_inputChannelMap.insert(pair<const unsigned long, unsigned int>(channelId, m_inputChannelIds.size())).first;
00047                 m_inputQueues.push_back(MessageQueue());
00048                 m_inputChannelIds.push_back(channelId);
00049 
00050                 if (m_inputChannelIds.size() == m_threshold)
00051                         PrepareInterpolation();
00052         }
00053         return m_lastMapPosition->second;
00054 }
00055 
00056 unsigned int RawIDA::LookupInputChannel(word32 channelId) const
00057 {
00058         map<word32, unsigned int>::const_iterator it = m_inputChannelMap.find(channelId);
00059         if (it == m_inputChannelMap.end())
00060                 return m_threshold;
00061         else
00062                 return it->second;
00063 }
00064 
00065 void RawIDA::ChannelData(word32 channelId, const byte *inString, unsigned int length)
00066 {
00067         unsigned int i = InsertInputChannel(channelId);
00068         if (i < m_threshold)
00069         {
00070                 unsigned long size = m_inputQueues[i].MaxRetrievable();
00071                 m_inputQueues[i].Put(inString, length);
00072                 if (size < 4 && size + length >= 4)
00073                 {
00074                         m_channelsReady++;
00075                         if (m_channelsReady == m_threshold)
00076                                 ProcessInputQueues();
00077                 }
00078         }
00079 }
00080 
00081 unsigned int RawIDA::InputBuffered(word32 channelId) const
00082 {
00083         unsigned int i = LookupInputChannel(channelId);
00084         return i < m_threshold ? m_inputQueues[i].MaxRetrievable() : 0;
00085 }
00086 
00087 void RawIDA::ChannelMessageEnd(const string &channel, int propagation)
00088 {
00089         unsigned int i = InsertInputChannel(StringToWord<word32>(channel));
00090         if (i < m_threshold)
00091         {
00092                 m_inputQueues[i].MessageEnd();
00093                 if (m_inputQueues[i].NumberOfMessages() == 1)
00094                 {
00095                         m_channelsFinished++;
00096                         if (m_channelsFinished == m_threshold)
00097                         {
00098                                 m_channelsReady = 0;
00099                                 for (i=0; i<m_threshold; i++)
00100                                         m_channelsReady += m_inputQueues[i].AnyRetrievable();
00101                                 ProcessInputQueues();
00102                         }
00103                 }
00104         }
00105 }
00106 
00107 void RawIDA::ComputeV(unsigned int i)
00108 {
00109         if (i >= m_v.size())
00110         {
00111                 m_v.resize(i+1);
00112                 m_outputToInput.resize(i+1);
00113         }
00114 
00115         m_outputToInput[i] = LookupInputChannel(m_outputChannelIds[i]);
00116         if (m_outputToInput[i] == m_threshold && i * m_threshold <= 1000*1000)
00117         {
00118                 m_v[i].Resize(m_threshold);
00119                 PrepareBulkPolynomialInterpolationAt(field, m_v[i].ptr, m_outputChannelIds[i], m_inputChannelIds.begin(), m_w.ptr, m_threshold);
00120         }
00121 }
00122 
00123 void RawIDA::AddOutputChannel(word32 channelId)
00124 {
00125         m_outputChannelIds.push_back(channelId);
00126         m_outputQueues.push_back(ByteQueue());
00127         m_channelSwitches.push_back(ChannelSwitch(*AttachedTransformation(), WordToString(channelId)));
00128         if (m_inputChannelIds.size() == m_threshold)
00129                 ComputeV(m_outputChannelIds.size() - 1);
00130 }
00131 
00132 void RawIDA::PrepareInterpolation()
00133 {
00134         assert(m_inputChannelIds.size() == m_threshold);
00135         PrepareBulkPolynomialInterpolation(field, m_w.ptr, m_inputChannelIds.begin(), m_threshold);
00136 //      polynomialRing.PrepareBulkInterpolation(m_w, m_inputChannelIds.begin(), m_threshold);
00137         for (unsigned int i=0; i<m_outputChannelIds.size(); i++)
00138                 ComputeV(i);
00139 }
00140 
00141 void RawIDA::ProcessInputQueues()
00142 {
00143         bool finished = (m_channelsFinished == m_threshold);
00144         unsigned int i;
00145 
00146         while (finished ? m_channelsReady > 0 : m_channelsReady == m_threshold)
00147         {
00148                 m_channelsReady = 0;
00149                 for (i=0; i<m_threshold; i++)
00150                 {
00151                         MessageQueue &queue = m_inputQueues[i];
00152                         queue.GetWord32(m_y[i]);
00153 
00154                         if (finished)
00155                                 m_channelsReady += queue.AnyRetrievable();
00156                         else
00157                                 m_channelsReady += queue.NumberOfMessages() > 0 || queue.MaxRetrievable() >= 4;
00158                 }
00159 
00160                 for (i=0; i<m_outputChannelIds.size(); i++)
00161                 {
00162                         if (m_outputToInput[i] != m_threshold)
00163                                 m_outputQueues[i].PutWord32(m_y[m_outputToInput[i]]);
00164                         else if (m_v[i].size == m_threshold)
00165                                 m_outputQueues[i].PutWord32(BulkPolynomialInterpolateAt(field, m_y.ptr, m_v[i].ptr, m_threshold));
00166                         else
00167                         {
00168                                 m_u.Resize(m_threshold);
00169                                 PrepareBulkPolynomialInterpolationAt(field, m_u.ptr, m_outputChannelIds[i], m_inputChannelIds.begin(), m_w.ptr, m_threshold);
00170                                 m_outputQueues[i].PutWord32(BulkPolynomialInterpolateAt(field, m_y.ptr, m_u.ptr, m_threshold));
00171                         }
00172                 }
00173         }
00174 
00175         if (m_outputChannelIds.size() > 0 && m_outputQueues[0].AnyRetrievable())
00176                 FlushOutputQueues();
00177 
00178         if (finished)
00179         {
00180                 OutputMessageEnds();
00181 
00182                 m_channelsReady = 0;
00183                 m_channelsFinished = 0;
00184                 m_v.clear();
00185 
00186                 vector<MessageQueue> inputQueues;
00187                 vector<word32> inputChannelIds;
00188 
00189                 inputQueues.swap(m_inputQueues);
00190                 inputChannelIds.swap(m_inputChannelIds);
00191                 m_inputChannelMap.clear();
00192                 m_lastMapPosition = m_inputChannelMap.end();
00193 
00194                 for (i=0; i<m_threshold; i++)
00195                 {
00196                         inputQueues[i].RetrieveNextMessage();
00197                         ChannelSwitch channelSwitch(*this, WordToString(inputChannelIds[i]));
00198                         inputQueues[i].TransferAllTo(channelSwitch);
00199                 }
00200         }
00201 }
00202 
00203 void RawIDA::FlushOutputQueues()
00204 {
00205         for (unsigned int i=0; i<m_outputChannelIds.size(); i++)
00206                 m_outputQueues[i].TransferTo(m_channelSwitches[i]);
00207 }
00208 
00209 void RawIDA::OutputMessageEnds()
00210 {
00211         if (GetAutoSignalPropagation() != 0)
00212         {
00213                 for (unsigned int i=0; i<m_outputChannelIds.size(); i++)
00214                         m_channelSwitches[i].MessageEnd(GetAutoSignalPropagation()-1);
00215         }
00216 }
00217 
00218 // ****************************************************************
00219 
00220 SecretSharing::SecretSharing(RandomNumberGenerator &rng, unsigned int threshold, unsigned int nShares, BufferedTransformation *outQueue, bool addPadding)
00221         : Filter(outQueue), m_rng(rng), m_ida(threshold, new OutputProxy(*this, true)), m_pad(addPadding)
00222 {
00223         for (unsigned int i=0; i<nShares; i++)
00224                 m_ida.AddOutputChannel(i);
00225 }
00226 
00227 void SecretSharing::Put(const byte *inString, unsigned int length)
00228 {
00229         SecByteBlock buf(STDMIN(length, 256U));
00230         unsigned int threshold = m_ida.GetThreshold();
00231         while (length > 0)
00232         {
00233                 unsigned int len = STDMIN(length, buf.size);
00234                 m_ida.ChannelData(0xffffffff, inString, len);
00235                 for (unsigned int i=0; i<threshold-1; i++)
00236                 {
00237                         m_rng.GenerateBlock(buf, len);
00238                         m_ida.ChannelData(i, buf, len);
00239                 }
00240                 length -= len;
00241                 inString += len;
00242         }
00243 }
00244 
00245 void SecretSharing::MessageEnd(int propagation)
00246 {
00247         m_ida.SetAutoSignalPropagation(propagation);
00248         if (m_pad)
00249         {
00250                 SecretSharing::Put(1);
00251                 while (m_ida.InputBuffered(0xffffffff) > 0)
00252                         SecretSharing::Put(0);
00253         }
00254         m_ida.ChannelMessageEnd(WordToString<word32>(0xffffffff));
00255         for (unsigned int i=0; i<m_ida.GetThreshold()-1; i++)
00256                 m_ida.ChannelMessageEnd(WordToString<word32>(i));
00257 }
00258 
00259 SecretRecovery::SecretRecovery(unsigned int threshold, BufferedTransformation *outQueue, bool removePadding)
00260         : RawIDA(threshold, outQueue), m_pad(removePadding)
00261 {
00262         AddOutputChannel(0xffffffff);
00263 }
00264 
00265 void SecretRecovery::FlushOutputQueues()
00266 {
00267         if (m_pad)
00268                 m_outputQueues[0].TransferTo(*AttachedTransformation(), m_outputQueues[0].MaxRetrievable()-4);
00269         else
00270                 m_outputQueues[0].TransferTo(*AttachedTransformation());
00271 }
00272 
00273 void SecretRecovery::OutputMessageEnds()
00274 {
00275         if (m_pad)
00276         {
00277                 PaddingRemover paddingRemover(new Redirector(*AttachedTransformation()));
00278                 m_outputQueues[0].TransferAllTo(paddingRemover);
00279         }
00280 
00281         if (GetAutoSignalPropagation() != 0)
00282                 AttachedTransformation()->MessageEnd(GetAutoSignalPropagation()-1);
00283 }
00284 
00285 // ****************************************************************
00286 
00287 InformationDispersal::InformationDispersal(unsigned int threshold, unsigned int nShares, BufferedTransformation *outQueue, bool addPadding)
00288         : Filter(outQueue), m_ida(threshold, new OutputProxy(*this, true)), m_pad(addPadding), m_nextChannel(0)
00289 {
00290         for (unsigned int i=0; i<nShares; i++)
00291                 m_ida.AddOutputChannel(i);
00292 }
00293 
00294 void InformationDispersal::Put(const byte *inString, unsigned int length)
00295 {
00296         while (length--)
00297         {
00298                 m_ida.ChannelData(m_nextChannel, inString, 1);
00299                 inString++;
00300                 m_nextChannel++;
00301                 if (m_nextChannel == m_ida.GetThreshold())
00302                         m_nextChannel = 0;
00303         }
00304 }
00305 
00306 void InformationDispersal::MessageEnd(int propagation)
00307 {
00308         m_ida.SetAutoSignalPropagation(propagation);
00309         if (m_pad)
00310                 InformationDispersal::Put(1);
00311         for (unsigned int i=0; i<m_ida.GetThreshold(); i++)
00312                 m_ida.ChannelMessageEnd(WordToString<word32>(i));
00313 }
00314 
00315 InformationRecovery::InformationRecovery(unsigned int threshold, BufferedTransformation *outQueue, bool removePadding)
00316         : RawIDA(threshold, outQueue), m_pad(removePadding)
00317 {
00318         for (unsigned int i=0; i<threshold; i++)
00319                 AddOutputChannel(i);
00320 }
00321 
00322 void InformationRecovery::FlushOutputQueues()
00323 {
00324         while (m_outputQueues[0].AnyRetrievable())
00325         {
00326                 for (unsigned int i=0; i<m_outputChannelIds.size(); i++)
00327                         m_outputQueues[i].TransferTo(m_queue, 1);
00328         }
00329 
00330         if (m_pad)
00331                 m_queue.TransferTo(*AttachedTransformation(), m_queue.MaxRetrievable()-4*m_threshold);
00332         else
00333                 m_queue.TransferTo(*AttachedTransformation());
00334 }
00335 
00336 void InformationRecovery::OutputMessageEnds()
00337 {
00338         if (m_pad)
00339         {
00340                 PaddingRemover paddingRemover(new Redirector(*AttachedTransformation()));
00341                 m_queue.TransferAllTo(paddingRemover);
00342         }
00343 
00344         if (GetAutoSignalPropagation() != 0)
00345                 AttachedTransformation()->MessageEnd(GetAutoSignalPropagation()-1);
00346 }
00347 
00348 void PaddingRemover::Put(byte b)
00349 {
00350         if (m_possiblePadding)
00351         {
00352                 if (b == 0)
00353                         m_zeroCount++;
00354                 else
00355                 {
00356                         AttachedTransformation()->Put(1);
00357                         while (m_zeroCount--)
00358                                 AttachedTransformation()->Put(0);
00359                         AttachedTransformation()->Put(b);
00360                         m_possiblePadding = false;
00361                 }
00362         }
00363         else
00364         {
00365                 if (b == 1)
00366                 {
00367                         m_possiblePadding = true;
00368                         m_zeroCount = 0;
00369                 }
00370                 else
00371                         AttachedTransformation()->Put(b);
00372         }
00373 }
00374 
00375 void PaddingRemover::Put(const byte *begin, unsigned int length)
00376 {
00377         const byte *const end = begin + length;
00378 
00379         if (m_possiblePadding)
00380         {
00381                 unsigned int len = find_if(begin, end, bind2nd(not_equal_to<byte>(), 0)) - begin;
00382                 m_zeroCount += len;
00383                 begin += len;
00384                 if (begin == end)
00385                         return;
00386                 PaddingRemover::Put(*begin++);
00387         }
00388 
00389 #if defined(_MSC_VER) && !defined(__MWERKS__)
00390         typedef reverse_iterator<const byte *, const byte> rit;
00391 #else
00392         typedef reverse_iterator<const byte *> rit;
00393 #endif
00394         const byte *x = find_if(rit(end), rit(begin), bind2nd(not_equal_to<byte>(), 0)).base();
00395         if (x != begin && *(x-1) == 1)
00396         {
00397                 AttachedTransformation()->Put(begin, x-begin-1);
00398                 m_possiblePadding = true;
00399                 m_zeroCount = end - x;
00400         }
00401         else
00402                 AttachedTransformation()->Put(begin, end-begin);
00403 }
00404 
00405 void PaddingRemover::MessageEnd(int propagation)
00406 {
00407         m_possiblePadding = false;
00408         Filter::MessageEnd(propagation);
00409 }
00410 
00411 NAMESPACE_END

Generated at Mon Jan 15 01:16:32 2001 for Crypto++ by doxygen1.2.4 written by Dimitri van Heesch, © 1997-2000