Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Combinatoric.h

00001 /*
00002  * Copyright 2003 Michael A. Marsh, Cornell University. All rights reserved.
00003  * This software is released under the modified BSD license.
00004  * See the file LICENSE in the top-level directory for details.
00005  */
00006 //
00007 // $Id: Combinatoric.h,v 1.4 2005/01/21 19:44:18 mmarsh Exp $
00008 //
00009 // $Log: Combinatoric.h,v $
00010 // Revision 1.4  2005/01/21 19:44:18  mmarsh
00011 // Updated for compatibility with Doxygen 1.4.1
00012 //
00013 // Revision 1.3  2004/05/19 15:57:00  mmarsh
00014 // *** empty log message ***
00015 //
00016 // Revision 1.2  2003/11/04 22:31:52  mmarsh
00017 // *** empty log message ***
00018 //
00019 //
00020 
00021 #ifndef __CODEX_VSS_COMBINATORIC_H__
00022 #define __CODEX_VSS_COMBINATORIC_H__
00023 
00024 #include <fstream>
00025 
00026 #include "CODEX_ASN1/SecureBigNumber.h"
00027 #include "CODEX_ASN1/Integer.h"
00028 #include "CODEX_Exceptions/BignumExceptions.h"
00029 #include "CODEX_Exceptions/FileExceptions.h"
00030 #include "ShareFunctional.h"
00031 #include "ShareSet.h"
00032 #include "CombinatoricScenario.h"
00033 #include "Range.h"
00034 
00035 namespace CODEX_VSS
00036 {
00040    template< int N , int T >
00041    struct choose
00042    {
00048          static const unsigned int value = N*choose<N-1,T-1>::value/T;
00049    };
00050 
00052    template< int N >
00053    struct choose<N,0>
00054    {
00056          static const unsigned int value = 1;
00057    };
00058 
00060    template< int N >
00061    struct choose<N,1>
00062    {
00064          static const unsigned int value = N;
00065    };
00066 
00071    template< unsigned int NumT , unsigned int ThreshT >
00072    class Combinatoric : public CODEX_ASN1::Base
00073    {
00074       public :
00076          typedef CODEX_ASN1::SecureBigNumber  ValueType;
00077 
00082          static const unsigned int NumShares = choose<NumT,ThreshT-1>::value+1;
00083 
00085          Combinatoric();
00086 
00088          Combinatoric( const Combinatoric<NumT,ThreshT>& aOther );
00089 
00091          Combinatoric( const ShareSet< Combinatoric<NumT,ThreshT> >& shareSet,
00092                        unsigned int partNum );
00093 
00095          virtual ~Combinatoric();
00096 
00098          void operator=( const Combinatoric<NumT,ThreshT>& aOther );
00099 
00107          void operator+=( const Combinatoric<NumT,ThreshT>& aOther );
00108 
00114          void setShare( unsigned int i,
00115                         const CODEX_ASN1::SecureBigNumber& share );
00116 
00121          const CODEX_ASN1::SecureBigNumber& share( unsigned int i ) const;
00122 
00124          unsigned int count() const;
00125 
00132          void apply( const ShareFunctional& func,
00133                      Combinatoric<NumT,ThreshT>& result ) const;
00134 
00140          void recover( CODEX_ASN1::SecureBigNumber& result ) const;
00141 
00142          int marshal( unsigned char ** pp ) const;
00143 
00144          void* unmarshal( void* bogus, unsigned char ** pp, long length );
00145 
00147          void toFile( const char* fname ) const;
00148 
00150          void* fromFile( const char* fname );
00151 
00152       private :
00153          CODEX_ASN1::SecureBigNumber  m_shares[ NumShares ];
00154    };
00155 
00156    template< unsigned int NumT , unsigned int ThreshT >
00157    Combinatoric<NumT,ThreshT>::Combinatoric() :
00158       CODEX_ASN1::Base( false )
00159    {
00160    }
00161 
00162    template< unsigned int NumT , unsigned int ThreshT >
00163    Combinatoric<NumT,ThreshT>::Combinatoric(
00164       const Combinatoric<NumT,ThreshT>& aOther ) :
00165       CODEX_ASN1::Base( aOther.m_initialized )
00166    {
00167       for ( unsigned int i = 0 ; i < NumShares ; ++i )
00168       {
00169          m_shares[i] = aOther.m_shares[i];
00170       }
00171    }
00172 
00173    template< unsigned int NumT , unsigned int ThreshT >
00174    Combinatoric<NumT,ThreshT>::Combinatoric(
00175       const ShareSet< Combinatoric<NumT,ThreshT> >& shareSet,
00176       unsigned int partNum ) :
00177       CODEX_ASN1::Base( true )
00178    {
00179       typedef CombinatoricScenario<NumT,ThreshT-1>  CSType;
00180       CSType* cs = CSType::instance();
00181       for ( unsigned int i = 0 ; i < NumShares ; ++i )
00182       {
00183          // Every participant gets the last share.
00184          if ( ( NumShares == (i+1) ) ||
00185               ( ! cs->inScenario( partNum, i ) ) )
00186          {
00187             m_shares[i] = shareSet(i);
00188          }
00189       }
00190    }
00191 
00192    template< unsigned int NumT , unsigned int ThreshT >
00193    Combinatoric<NumT,ThreshT>::~Combinatoric()
00194    {
00195    }
00196 
00197    template< unsigned int NumT , unsigned int ThreshT >
00198    void
00199    Combinatoric<NumT,ThreshT>::operator=(
00200       const Combinatoric<NumT,ThreshT>& aOther )
00201    {
00202       m_initialized = aOther.m_initialized;
00203       for ( unsigned int i = 0 ; i < NumShares ; ++i )
00204       {
00205          m_shares[i] = aOther.m_shares[i];
00206       }
00207    }
00208 
00209    template< unsigned int NumT , unsigned int ThreshT >
00210    void
00211    Combinatoric<NumT,ThreshT>::operator+=(
00212       const Combinatoric<NumT,ThreshT>& aOther )
00213    {
00214       if ( ! aOther.m_initialized )
00215       {
00216          return;
00217       }
00218       m_initialized = true;
00219       for ( unsigned int i = 0 ; i < NumShares ; ++i )
00220       {
00221          if ( ! m_shares[i].initialized() )
00222          {
00223             m_shares[i] = aOther.m_shares[i];
00224          }
00225       }
00226    }
00227 
00228    template< unsigned int NumT , unsigned int ThreshT >
00229    void
00230    Combinatoric<NumT,ThreshT>::setShare(
00231       unsigned int i,
00232       const CODEX_ASN1::SecureBigNumber& share )
00233    {
00234       if ( i >= NumShares )
00235       {
00236          throw CODEX_Exceptions::IllegalIndexException( __FILE__ , __LINE__ );
00237       }
00238       m_shares[i] = share;
00239       m_initialized = true;
00240    }
00241 
00242    template< unsigned int NumT , unsigned int ThreshT >
00243    const CODEX_ASN1::SecureBigNumber&
00244    Combinatoric<NumT,ThreshT>::share( unsigned int i ) const
00245    {
00246       if ( i >= NumShares )
00247       {
00248          throw CODEX_Exceptions::IllegalIndexException( __FILE__ , __LINE__ );
00249       }
00250       return m_shares[i];
00251    }
00252 
00253    template< unsigned int NumT , unsigned int ThreshT >
00254    unsigned int
00255    Combinatoric<NumT,ThreshT>::count() const
00256    {
00257       unsigned int retVal = 0;
00258       for ( unsigned int i = 0 ; i < NumShares ; ++i )
00259       {
00260          if ( m_shares[i].initialized() )
00261          {
00262             ++retVal;
00263          }
00264       }
00265       return retVal;
00266    }
00267 
00268    template< unsigned int NumT , unsigned int ThreshT >
00269    void
00270    Combinatoric<NumT,ThreshT>::apply( const ShareFunctional& func,
00271                                       Combinatoric<NumT,ThreshT>& result )
00272       const
00273    {
00274       result.m_initialized = true;
00275       for ( unsigned int i = 0 ; i < NumShares ; ++i )
00276       {
00277          if ( m_shares[i].initialized() )
00278          {
00279             func( m_shares[i] , result.m_shares[i] );
00280          }
00281       }
00282    }
00283 
00284    template< unsigned int NumT , unsigned int ThreshT >
00285    void
00286    Combinatoric<NumT,ThreshT>::recover( CODEX_ASN1::SecureBigNumber& result )
00287       const
00288    {
00289       if ( result.initialized() )
00290       {
00291          result = CODEX_ASN1::SecureBigNumber(); // reset
00292       }
00293       if ( ! m_initialized )
00294       {
00295          return;
00296       }
00297       for ( unsigned int i = 0 ; i < NumShares ; ++i )
00298       {
00299          if ( ! m_shares[i].initialized() )
00300          {
00301             return;
00302          }
00303       }
00304       BIGNUM * r = 0;
00305       try
00306       {
00307          r = BN_new();
00308          if ( 0 == r )
00309          {
00310             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00311          }
00312          if ( ! BN_zero(r) )
00313          {
00314             throw CODEX_Exceptions::BignumSetWordException( __FILE__ ,
00315                                                             __LINE__ );
00316          }
00317          for ( unsigned int i = 0 ; i < NumShares ; ++i )
00318          {
00319             if ( ! BN_add( r, r, m_shares[i].value() ) )
00320             {
00321                throw CODEX_Exceptions::BignumAddException( __FILE__ ,
00322                                                            __LINE__ );
00323             }
00324          }
00325          result = CODEX_ASN1::SecureBigNumber( r );
00326       }
00327       catch ( ... )
00328       {
00329          if ( 0 != r ) BN_clear_free(r);
00330          throw;
00331       }
00332    }
00333 
00334    template< unsigned int NumT , unsigned int ThreshT >
00335    int
00336    Combinatoric<NumT,ThreshT>::marshal( unsigned char ** pp ) const
00337    {
00338       int r=0;
00339       int ret=0;
00340       unsigned char * p;
00341 
00342       CODEX_ASN1::Integer isSet[NumShares];
00343       for ( unsigned int counter = 0 ; counter < NumShares ; ++counter )
00344       {
00345          isSet[counter] =
00346             CODEX_ASN1::Integer( m_shares[counter].initialized() ? 1 : 0 );
00347       }
00348       for ( unsigned int counter = 0 ; counter < NumShares ; ++counter )
00349       {
00350          ret += isSet[counter].marshal(0);
00351          if ( isSet[counter].value() )
00352          {
00353             ret += m_shares[counter].marshal(0);
00354          }
00355       }
00356       M_ASN1_I2D_seq_total();
00357       for ( unsigned int counter = 0 ; counter < NumShares ; ++counter )
00358       {
00359          isSet[counter].marshal(&p);
00360          if ( isSet[counter].value() )
00361          {
00362             m_shares[counter].marshal(&p);
00363          }
00364       }
00365       M_ASN1_I2D_finish();
00366    }
00367 
00368    template< unsigned int NumT , unsigned int ThreshT >
00369    void*
00370    Combinatoric<NumT,ThreshT>::unmarshal( void* bogus,
00371                                           unsigned char ** pp,
00372                                           long length )
00373    {
00374       if ( m_initialized )
00375       {
00376          return 0;
00377       }
00378       if ( (0 == pp) || (0 == *pp) )
00379       {
00380          return 0;
00381       }
00382       ASN1_CTX c;
00383       c.pp = pp;
00384       c.q = *pp;
00385       c.error = ERR_R_NESTED_ASN1_ERROR;
00386       int i;
00387 
00388       M_ASN1_D2I_Init();
00389       M_ASN1_D2I_start_sequence();
00390       for ( unsigned int counter = 0 ; counter < NumShares ; ++counter )
00391       {
00392          CODEX_ASN1::Integer isSet;
00393          M_ASN1_D2I_get(i, isSet.unmarshal);
00394          if ( isSet.value() )
00395          {
00396             M_ASN1_D2I_get(i, m_shares[counter].unmarshal);
00397          }
00398       }
00399       if ( !asn1_Finish(&c) )
00400       {
00401          return 0;
00402       }
00403       *pp=c.p;
00404       m_initialized = true;
00405       return this;
00406      err: // needed by ASN.1 macros
00407       return 0;
00408    }
00409 
00410    template< unsigned int NumT , unsigned int ThreshT >
00411    void
00412    Combinatoric<NumT,ThreshT>::toFile( const char* fname ) const
00413    {
00414       int length = marshal(0);
00415       if ( 0 == length ) return;
00416       unsigned char* buff = new unsigned char[length];
00417       unsigned char* p = buff;
00418       marshal(&p);
00419       ofstream os(fname);
00420       if ( ! os.is_open() )
00421       {
00422          delete [] buff;
00423          throw CODEX_Exceptions::FileCannotCreateException( __FILE__ ,
00424                                                             __LINE__ ,
00425                                                             fname );
00426       }
00427       for ( int i = 0 ; i < length ; ++i )
00428       {
00429          os << buff[i];
00430       }
00431       os.close();
00432       delete [] buff;
00433    }
00434 
00435    template< unsigned int NumT , unsigned int ThreshT >
00436    void*
00437    Combinatoric<NumT,ThreshT>::fromFile( const char* fname )
00438    {
00439       ifstream is(fname);
00440       if ( ! is.is_open() )
00441       {
00442          throw CODEX_Exceptions::FileCannotOpenException( __FILE__ ,
00443                                                           __LINE__ ,
00444                                                           fname );
00445       }
00446       string s;
00447       char ch;
00448       while ( is.get(ch) )
00449       {
00450          s.push_back(ch);
00451       }
00452       //basic_string<unsigned char> s;
00453       //is >> s;
00454       unsigned int length = s.length();
00455       unsigned char* p = new unsigned char[length];
00456       unsigned char* pOrig = p;
00457       //unsigned char* p = (unsigned char*)s.data();
00458       for ( unsigned int i = 0 ; i < length ; ++i )
00459       {
00460          p[i] = s.data()[i];
00461       }
00462       return unmarshal(0,&p,length);
00463       delete [] pOrig;
00464    }
00465 
00466 
00468    template< unsigned int NumT , unsigned int ThreshT >
00469    class ShareSet< Combinatoric<NumT,ThreshT> >
00470    {
00471       public :
00473          typedef Combinatoric<NumT,ThreshT>  ShareType;
00474 
00476          ShareSet() {}
00477 
00479          ShareSet( const ShareSet< ShareType >& aOther ) :
00480             m_shares( aOther.m_shares )
00481          {}
00482 
00484          void operator=( const ShareSet< ShareType >& aOther )
00485          {
00486             m_shares = aOther.m_shares;
00487          }
00488 
00497          const typename ShareType::ValueType& operator()( unsigned int i )
00498             const
00499          {
00500             return m_shares.share(i);
00501          }
00502 
00510          void setShare( unsigned int i,
00511                         const typename ShareType::ValueType& share )
00512          {
00513             m_shares.setShare(i,share);
00514          }
00515 
00517          void addShare( const ShareType& share )
00518          {
00519             m_shares += share;
00520          }
00521 
00527          void recover( CODEX_ASN1::SecureBigNumber& result ) const
00528          {
00529             return m_shares.recover( result );
00530          }
00531 
00541          bool shouldHave( unsigned int shareNum, unsigned int partNum ) const
00542          {
00543             typedef CombinatoricScenario<NumT,ThreshT-1>  CSType;
00544             CSType* cs = CSType::instance();
00545             if ( shareNum + 1 == ShareType::NumShares )
00546             {
00547                return true;
00548             }
00549             return ( ! cs->inScenario( partNum, shareNum ) );
00550          }
00551 
00552       private :
00553          ShareType  m_shares;
00554    };
00555 
00557    template< unsigned int NumT , unsigned int ThreshT >
00558    class ShareSplitting< Combinatoric<NumT,ThreshT> >
00559    {
00560       public :
00562          typedef Combinatoric<NumT,ThreshT>  ShareType;
00563 
00565          const static unsigned int           NumShares = ShareType::NumShares;
00566 
00576          static void split( const BIGNUM* secret,
00577                             ShareSet< ShareType >& shareSet,
00578                             const Range& range )
00579          {
00580             const BIGNUM * minVal = range.min();
00581             const BIGNUM * maxVal = range.max();
00582             BIGNUM * m = 0;
00583             BIGNUM * temp = 0;
00584             BIGNUM * total = 0;
00585             BIGNUM * remainder = 0;
00586             try
00587             {
00588                m = BN_new();
00589                if ( 0 == m )
00590                {
00591                   throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00592                                                                __LINE__ );
00593                }
00594                total = BN_new();
00595                if ( 0 == total )
00596                {
00597                   throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00598                                                                __LINE__ );
00599                }
00600                remainder = BN_new();
00601                if ( 0 == remainder )
00602                {
00603                   throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00604                                                                __LINE__ );
00605                } 
00606 
00607                if ( ! BN_sub( m, maxVal, minVal ) )
00608                {
00609                   throw CODEX_Exceptions::BignumSubException( __FILE__ ,
00610                                                               __LINE__ );
00611                }
00612                if ( ! BN_add( m, m, BN_value_one() ) )
00613                {
00614                   throw CODEX_Exceptions::BignumAddException( __FILE__ ,
00615                                                               __LINE__ );
00616                }
00617 
00618                for ( unsigned int i = 0 ; i < NumShares - 1 ; ++i )
00619                {
00620                   temp = BN_new();
00621                   if ( 0 == temp )
00622                   {
00623                      throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00624                                                                   __LINE__ );
00625                   }
00626                   if ( ! BN_rand_range( temp, m ) )
00627                   {
00628                      throw
00629                         CODEX_Exceptions::BignumRandRangeException( __FILE__ ,
00630                                                                     __LINE__ );
00631                   }
00632                   if ( ! BN_add( temp, temp, minVal ) )
00633                   {
00634                      throw CODEX_Exceptions::BignumAddException( __FILE__ ,
00635                                                                  __LINE__ );
00636                   }
00637 
00638                   if ( ! BN_add( total, total, temp ) )
00639                   {
00640                      throw CODEX_Exceptions::BignumAddException( __FILE__ ,
00641                                                                  __LINE__ );
00642                   }
00643                   shareSet.setShare(i,ShareType::ValueType(temp));
00644                   temp = 0;  // temp's memory is taken over above
00645                }
00646 
00647                if ( ! BN_sub( remainder, secret, total ) )
00648                {
00649                   throw CODEX_Exceptions::BignumSubException( __FILE__ ,
00650                                                               __LINE__ );
00651                }
00652                shareSet.setShare(NumShares-1,ShareType::ValueType(remainder));
00653                remainder = 0; // remainder's memory is taken over above
00654                BN_clear_free(total);
00655                BN_free(m);
00656             }
00657             catch ( ... )
00658             {
00659                if ( 0 != m ) BN_free(m);
00660                if ( 0 != temp ) BN_clear_free(temp);
00661                if ( 0 != total ) BN_clear_free(total);
00662                if ( 0 != remainder ) BN_clear_free(remainder);
00663                throw;
00664             }
00665          }
00666    };
00667 
00668 }
00669 
00670 #endif /* __CODEX_VSS_COMBINATORIC_H__*/

Generated on Fri May 6 17:38:55 2005 for COrnell Data EXchange (CODEX) by  doxygen 1.4.1