Wiselib
wiselib.testing/algorithms/crypto/ZeroKnowledgeProofsFp/schnorr-zkpnint-prover.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  ** This file is part of the generic algorithm library Wiselib.           **
00003  ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project.      **
00004  **                                                                       **
00005  ** The Wiselib is free software: you can redistribute it and/or modify   **
00006  ** it under the terms of the GNU Lesser General Public License as        **
00007  ** published by the Free Software Foundation, either version 3 of the    **
00008  ** License, or (at your option) any later version.                       **
00009  **                                                                       **
00010  ** The Wiselib is distributed in the hope that it will be useful,        **
00011  ** but WITHOUT ANY WARRANTY; without even the implied warranty of        **
00012  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         **
00013  ** GNU Lesser General Public License for more details.                   **
00014  **                                                                       **
00015  ** You should have received a copy of the GNU Lesser General Public      **
00016  ** License along with the Wiselib.                                       **
00017  ** If not, see <http://www.gnu.org/licenses/>.                           **
00018  ***************************************************************************/
00019 
00020 #ifndef __ALGORITHMS_CRYPTO_ZKPNINTPROVER_H_
00021 #define __ALGORITHMS_CRYPTO_ZKPNINTPROVER_H_
00022 
00023 #include "algorithms/crypto/eccfp.h"
00024 #include "algorithms/crypto/pmp.h"
00025 #include "algorithms/crypto/sha1.h"
00026 #include <string.h>
00027 
00028 //Uncomment to enable Debug
00029 #define ENABLE_ZKPNINT_DEBUG
00030 
00031 /* PROTOCOL DESCRIPTION
00032 
00033 Non-interactive Schnorr's Protocol
00034 
00035 Prover and Verifier agree on an elliptic curve E over a field Fn , a generator
00036 G in E/Fn , P in E/Fn and a hash function HASH (e.g. SHA-1). Both know
00037 B in E/Fn and Prover claims that he knows x such that B = x*G.
00038 
00039 Protocol Steps
00040 
00041 1. Prover generates random r and computes A = r*G
00042 2. Prover computes c = HASH(x*P, r*P, r*G)
00043 3. Prover computes s = r + cx
00044 4. Prover sends to Verifier the message : " s||x*P ||r*P ||r*G "
00045 5. Verifier computes c = HASH(x*P, r*P, r*G)
00046 6. Verifier checks that s*G = (r + cx)*G = r*G + cx*G = r*G + c*B
00047 7. Verifier checks that s*P = (r + cx)*P = r*P + cx*P = r*P + c*xP
00048 */
00049 
00050 namespace wiselib {
00051 
00052 template<typename OsModel_P, typename Radio_P = typename OsModel_P::Radio, typename Debug_P = typename OsModel_P::Debug>
00053    class ZKPNINTProve
00054    {
00055    public:
00056       typedef OsModel_P OsModel;
00057       typedef Radio_P Radio;
00058       typedef Debug_P Debug;
00059 
00060       typedef ZKPNINTProve<OsModel_P, Radio_P, Debug_P> self_t;
00061      typedef typename Radio::node_id_t node_id_t;
00062      typedef typename Radio::size_t size_t;
00063      typedef typename Radio::block_data_t block_data_t;
00064      typedef self_t* self_pointer_t;
00065 
00068       ZKPNINTProve();
00069       ~ZKPNINTProve();
00071 
00075 
00076       //message types
00077       enum MsgHeaders {
00078         START_MSG = 200,
00079         START_MSG_CONT = 201,
00080         ACCEPT_MSG = 202,
00081         REJECT_MSG = 203
00082        };
00083 
00085       //key setup needs 2 public keys one for the proof and one agreed
00086       void key_setup(NN_DIGIT *privkey, Point *pubkey, Point *pubkey2);
00087       void start_proof();
00088       void send_content();
00089 
00090       int init( Radio& radio, Debug& debug )
00091      {
00092        radio_ = &radio;
00093        debug_ = &debug;
00094        return 0;
00095      }
00096 
00097      inline int init();
00098      inline int destruct();
00099 
00100      int enable_radio( void );
00101      int disable_radio( void );
00102 
00103    protected:
00104            void receive( node_id_t from, size_t len, block_data_t *data );
00105 
00106    private:
00107 
00108    Radio& radio()
00109    { return *radio_; }
00110 
00111    Debug& debug()
00112    { return *debug_; }
00113 
00114    typename Radio::self_pointer_t radio_;
00115    typename Debug::self_pointer_t debug_;
00116 
00117    //necessary class objects
00118    ECCFP eccfp;
00119    PMP pmp;
00120 
00121    //rounds of the protocol used for seeding the rand function
00122    uint16_t rounds;
00123 
00124    //private key that only the prover knows
00125    NN_DIGIT m[NUMWORDS];
00126 
00127    //public key that both prover and verifier know
00128    Point B;
00129 
00130    //public key that represents the message
00131    Point P;
00132 
00133    //private key r that is generated in every round and
00134    //its corresponding public key
00135    NN_DIGIT r[NUMWORDS];
00136    Point A;
00137 
00138    //data that will be sent to the verifier
00139    NN_DIGIT s[NUMWORDS];
00140    Point RP;
00141    Point MP;
00142 
00143    };
00144 
00145    // -----------------------------------------------------------------------
00146    template<typename OsModel_P,
00147       typename Radio_P,
00148       typename Debug_P>
00149    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00150 	ZKPNINTProve()
00151    : radio_(0),
00152      debug_(0)
00153    {}
00154    // -----------------------------------------------------------------------
00155    template<typename OsModel_P,
00156       typename Radio_P,
00157       typename Debug_P>
00158    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00159 	~ZKPNINTProve()
00160    {}
00161    //-----------------------------------------------------------------------
00162    template<typename OsModel_P,
00163          typename Radio_P,
00164          typename Debug_P>
00165    int
00166    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00167 	init( void )
00168    {
00169      enable_radio();
00170      return 0;
00171    }
00172    //-----------------------------------------------------------------------------
00173    template<typename OsModel_P,
00174          typename Radio_P,
00175          typename Debug_P>
00176    int
00177    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00178 	destruct( void )
00179    {
00180      return disable_radio();
00181    }
00182    //---------------------------------------------------------------------------
00183    template<typename OsModel_P,
00184          typename Radio_P,
00185          typename Debug_P>
00186    int
00187    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00188 	enable_radio( void )
00189    {
00190 #ifdef ENABLE_ZKPNINT_DEBUG
00191       debug().debug( "ZKPProve: Boot for %i\n", radio().id() );
00192 #endif
00193 
00194      radio().enable_radio();
00195      radio().template reg_recv_callback<self_t, &self_t::receive>( this );
00196 
00197      return 0;
00198    }
00199    //---------------------------------------------------------------------------
00200    template<typename OsModel_P,
00201          typename Radio_P,
00202          typename Debug_P>
00203    int
00204    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00205 	disable_radio( void )
00206    {
00207 #ifdef ENABLE_ZKPNINT_DEBUG
00208       debug().debug( "ZKPProve: Disable\n" );
00209 #endif
00210      return -1;
00211    }
00212    //-----------------------------------------------------------------------
00213    template<typename OsModel_P,
00214             typename Radio_P,
00215             typename Debug_P>
00216    void
00217    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00218 	key_setup( NN_DIGIT *privkey, Point *pubkey, Point *pubkey2) {
00219 
00220       rounds=1;
00221 
00222       //prover's private secret key
00223       pmp.AssignZero(m, NUMWORDS);
00224       pmp.Assign(m, privkey, NUMWORDS);
00225 
00226       //public key available to prover and verifier
00227       eccfp.p_clear(&B);
00228       eccfp.p_copy(&B, pubkey);
00229 
00230       //message available to prover and verifier
00231       eccfp.p_clear(&P);
00232       eccfp.p_copy(&P, pubkey2);
00233    }
00234 
00235    //---------------------------------------------------------------------------
00236    template<typename OsModel_P,
00237             typename Radio_P,
00238             typename Debug_P>
00239    void
00240    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00241 	start_proof( void ) {
00242 
00243 #ifdef ENABLE_ZKPNINT_DEBUG
00244       debug().debug("Debug::Start ZKP Non-interactive Prover on::%d \n", radio().id());
00245 #endif
00246 
00247       //if the protocol is booting generate random r and compute Verify=rG
00248       //compute the c = HASH(mP , rP, Verify)
00249       //compute s = r + cm and send "s || mP || rP || Verify"  to verifier
00250 
00251       rounds++;
00252       //clear the private key and public key
00253       pmp.AssignZero(r, NUMWORDS);
00254       eccfp.p_clear(&A);
00255 
00256 #ifdef ENABLE_ZKPNINT_DEBUG
00257       debug().debug("Debug::Generating random r and computing A=rG. ::%d \n", radio().id() );
00258 #endif
00259       //generate random r and compute A=rG
00260       eccfp.gen_private_key(r, rounds);
00261       eccfp.gen_public_key(&A, r);
00262 
00263 #ifdef ENABLE_ZKPNINT_DEBUG
00264       debug().debug("Debug::Computing mP. ::%d \n", radio().id() );
00265 #endif
00266       //compute mP
00267       eccfp.p_clear(&MP);
00268       eccfp.c_mul(&MP, &P, m);
00269 
00270 #ifdef ENABLE_ZKPNINT_DEBUG
00271       debug().debug("Debug::Computing rP. ::%d \n", radio().id() );
00272 #endif
00273       //compute rP
00274       eccfp.p_clear(&RP);
00275       eccfp.c_mul(&RP, &P, r);
00276 
00277       //compute c=HASH(mP, rP, A)
00278       block_data_t input[6*(KEYDIGITS * NN_DIGIT_LEN +1)];
00279       for(int16_t i=0; i< 6*(KEYDIGITS*NN_DIGIT_LEN +1); i++)
00280       {
00281          input[i]=0;
00282       }
00283       block_data_t b[20];
00284       //convert point mP to octet and place to input
00285       eccfp.point2octet(input, 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &MP, FALSE);
00286       //convert point rP to octet and place to input
00287       eccfp.point2octet(input + 2*(KEYDIGITS*NN_DIGIT_LEN + 1), 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &RP, FALSE);
00288       //convert point A to octet and place to input
00289       eccfp.point2octet(input + 4*(KEYDIGITS*NN_DIGIT_LEN + 1), 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &A, FALSE);
00290 
00291       //digest
00292       SHA1Context sha;
00293       SHA1::SHA1Reset(&sha);
00294       SHA1::SHA1Update(&sha, input, 6*(KEYDIGITS * NN_DIGIT_LEN +1));
00295       SHA1::SHA1Digest(&sha, b);
00296 
00297       //place the hash in a key
00298       NN_DIGIT key[NUMWORDS];
00299       NN_DIGIT c[NUMWORDS];
00300       pmp.AssignZero(key, NUMWORDS);
00301       pmp.AssignZero(c, NUMWORDS);
00302       //decode the private key received
00303       pmp.Decode(key, NUMWORDS, b, 20);
00304       //mod n the hash output
00305       pmp.Mod(c, key, NUMWORDS, param.r, NUMWORDS);
00306 
00307       //compute s = r + cm
00308       NN_DIGIT mid2[NUMWORDS];
00309       pmp.AssignZero(mid2, NUMWORDS);
00310 
00311       //first compute cm
00312       pmp.ModMult(mid2, c, m, param.r, NUMWORDS);
00313       //then add r+cm
00314       pmp.AssignZero(s, NUMWORDS);
00315       pmp.ModAdd(s, r, mid2, param.r, NUMWORDS);
00316 
00317 #ifdef ENABLE_ZKPNINT_DEBUG
00318       debug().debug("Debug::Finished calculations!Calling the send_content() function. ::%d \n", radio().id() );
00319 #endif
00320       send_content();
00321    }
00322 
00323    //------------------------------------------------------------------------
00324    template<typename OsModel_P,
00325             typename Radio_P,
00326             typename Debug_P>
00327    void
00328    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00329 	send_content( void ) {
00330 
00331 #ifdef ENABLE_ZKPNINT_DEBUG
00332       debug().debug("Debug::Creating the message content::%d \n", radio().id() );
00333 #endif
00334 
00335       //send the message "s || mP || rP || A"
00336       //in 2 pieces as it cannot fit in a single radio packet
00337       //e.g. iSense Radio max payload = 116 bytes
00338 
00339       //first piece s || mP
00340       block_data_t buffer[1 + 3*(KEYDIGITS*NN_DIGIT_LEN +1)];
00341       buffer[0]=START_MSG;
00342 
00343       //convert s to octet and place to buffer
00344       pmp.Encode(buffer+1, KEYDIGITS * NN_DIGIT_LEN +1, s, NUMWORDS);
00345 
00346       //convert the point mP to octet and place to buffer
00347       eccfp.point2octet(buffer + 1 + (KEYDIGITS*NN_DIGIT_LEN +1), 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &MP, FALSE);
00348 
00349 #ifdef ENABLE_ZKPNINT_DEBUG
00350       debug().debug("Debug::Sending The First Part of the Content::%d \n", radio().id() );
00351 #endif
00352       radio().send(Radio::BROADCAST_ADDRESS, 1 + 3*(KEYDIGITS*NN_DIGIT_LEN +1), buffer);
00353 
00354       //now send second piece rP || rG
00355       block_data_t buf2[1 + 4*(KEYDIGITS * NN_DIGIT_LEN +1)];
00356       buf2[0]=START_MSG_CONT;
00357 
00358       //convert the point rP to octet and place to buffer
00359       eccfp.point2octet(buf2+1, 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &RP, FALSE);
00360 
00361       //convert the point A = rG to octet and place to buffer
00362       eccfp.point2octet(buf2+1+2*(KEYDIGITS*NN_DIGIT_LEN + 1), 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &A, FALSE);
00363 
00364 #ifdef ENABLE_ZKPNINT_DEBUG
00365       debug().debug("Debug::Sending The Second Part of the Content::%d \n", radio().id() );
00366 #endif
00367       radio().send(Radio::BROADCAST_ADDRESS, 1 + 4*(KEYDIGITS * NN_DIGIT_LEN +1), buf2);
00368    }
00369 
00370    //---------------------------------------------------------------------------
00371    template<typename OsModel_P,
00372             typename Radio_P,
00373             typename Debug_P>
00374    void
00375    ZKPNINTProve<OsModel_P, Radio_P, Debug_P>::
00376 	receive( node_id_t from, size_t len, block_data_t *data ) {
00377 
00378       if( from == radio().id() ) return;
00379 
00380       if(data[0]==ACCEPT_MSG)
00381       {
00382 #ifdef ENABLE_ZKPNINT_DEBUG
00383          debug().debug("Debug::I got ACCEPTED from the verifier.YESSS!::%d \n", radio().id());
00384 #endif
00385       }
00386 
00387       if(data[0]==REJECT_MSG)
00388       {
00389 #ifdef ENABLE_ZKPNINT_DEBUG
00390          debug().debug("Debug::I got REJECTED from the verifier.NOOO!::%d \n", radio().id() );
00391 #endif
00392       }
00393    }
00394 
00395 } //end of wiselib namespace
00396 
00397 #endif /* ZKPNINTPROVER_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines