Wiselib
wiselib.testing/algorithms/crypto/ZeroKnowledgeProofsFp/schnorr-zkp-verifier.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_SCHNORRZKP_VERIFIER_H_
00021 #define __ALGORITHMS_SCHNORRZKP_VERIFIER_H_
00022 
00023 #include "algorithms/crypto/eccfp.h"
00024 #include "algorithms/crypto/sha1.h"
00025 
00026 #include <string.h>
00027 
00028 //protocol needs to be executed for 1 round
00029 #define REQ_ROUNDS 1
00030 
00031 // Uncomment to enable Debug
00032 #define ENABLE_SCHNORRZKP_DEBUG
00033 
00034 /* PROTOCOL DESCRIPTION
00035 
00036 Schnorr's Protocol
00037 
00038 Prover and Verifier agree on an elliptic curve E over a field Fn , a generator
00039 G in E/Fn . They both know B in E/Fn and Prover claims he knows x such
00040 that B = x * G.
00041 
00042 Protocol Steps
00043 
00044 1. Prover generates random r and computes A = r * G
00045 2. Prover sends A to Verifier
00046 3. Verifier computes c = HASH(G, B, A) and sends c to Prover
00047 4. Prover computes m = r + cx and sends m to Verifier
00048 5 Verifier checks that P = m*G-c*B =(r+cx)*G-c*B = r*G+cx*G - c*xG = A
00049 and that HASH(G, B, P ) = c.
00050 */
00051 
00052 namespace wiselib {
00053 
00054 template<typename OsModel_P, typename Radio_P = typename OsModel_P::Radio, typename Debug_P = typename OsModel_P::Debug>
00055    class SCHNORRZKPVerify
00056    {
00057    public:
00058       typedef OsModel_P OsModel;
00059       typedef Radio_P Radio;
00060       typedef Debug_P Debug;
00061 
00062       typedef SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P> self_t;
00063      typedef typename Radio::node_id_t node_id_t;
00064      typedef typename Radio::size_t size_t;
00065      typedef typename Radio::block_data_t block_data_t;
00066      typedef self_t* self_pointer_t;
00067 
00070       SCHNORRZKPVerify();
00071       ~SCHNORRZKPVerify();
00073 
00077 
00078       //message types
00079       //message types
00080       enum MsgHeaders {
00081         START_MSG = 200,
00082         HASH_MSG = 201,
00083         CONT_MSG = 202,
00084         ACCEPT_MSG = 203,
00085         REJECT_MSG = 204
00086        };
00087 
00088       int init( Radio& radio, Debug& debug )
00089      {
00090        radio_ = &radio;
00091        debug_ = &debug;
00092        return 0;
00093      }
00094 
00095       inline int init();
00096      inline int destruct();
00097 
00098      int enable_radio( void );
00099      int disable_radio( void );
00100 
00102       void key_setup(Point *pubkey);
00103       void compute_hash();
00104       void verify();
00105       void final_decision();
00106 
00107    protected:
00108            void receive( node_id_t from, size_t len, block_data_t *data );
00109 
00110    private:
00111 
00112    Radio& radio()
00113    { return *radio_; }
00114 
00115    Debug& debug()
00116    { return *debug_; }
00117 
00118    typename Radio::self_pointer_t radio_;
00119    typename Debug::self_pointer_t debug_;
00120 
00121    //necessary class objects
00122    ECCFP eccfp;
00123    PMP pmp;
00124 
00125       //# of successfull rounds
00126    uint8_t success_rounds;
00127 
00128    //# of required rounds
00129    uint8_t required_rounds;
00130 
00131    //the hash calculated on the point received by the prover
00132    NN_DIGIT c[NUMWORDS];
00133 
00134    //private key that will be received by the prover in each round
00135    NN_DIGIT Valid[NUMWORDS];
00136 
00137    //public key that both prover and verifier know
00138    Point B;
00139 
00140    //public key A to be received by the prover
00141    Point A;
00142 
00143    //public key P for the verifications
00144    Point P;
00145 
00146    };
00147 
00148    // -----------------------------------------------------------------------
00149    template<typename OsModel_P,
00150          typename Radio_P,
00151          typename Debug_P>
00152    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00153 	SCHNORRZKPVerify()
00154    :radio_(0),
00155     debug_(0)
00156    {}
00157 
00158    // -----------------------------------------------------------------------
00159    template<typename OsModel_P,
00160          typename Radio_P,
00161          typename Debug_P>
00162    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00163 	~SCHNORRZKPVerify()
00164    {}
00165 
00166    //-----------------------------------------------------------------------
00167    template<typename OsModel_P,
00168          typename Radio_P,
00169          typename Debug_P>
00170    int
00171    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00172 	init( void )
00173    {
00174      enable_radio();
00175      return 0;
00176    }
00177    //-----------------------------------------------------------------------------
00178    template<typename OsModel_P,
00179          typename Radio_P,
00180          typename Debug_P>
00181    int
00182    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00183 	destruct( void )
00184    {
00185      return disable_radio();
00186    }
00187    //---------------------------------------------------------------------------
00188    template<typename OsModel_P,
00189          typename Radio_P,
00190          typename Debug_P>
00191    int
00192    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00193 	enable_radio( void )
00194    {
00195 #ifdef ENABLE_SCHNORRZKP_DEBUG
00196       debug().debug( "SCHNORR-ZKP-Verify: Boot for %i\n", radio().id() );
00197 #endif
00198 
00199      radio().enable_radio();
00200      radio().template reg_recv_callback<self_t, &self_t::receive>( this );
00201 
00202      return 0;
00203    }
00204    //---------------------------------------------------------------------------
00205    template<typename OsModel_P,
00206          typename Radio_P,
00207          typename Debug_P>
00208    int
00209    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00210 	disable_radio( void )
00211    {
00212 #ifdef ENABLE_SCHNORRZKP_DEBUG
00213       debug().debug( "SCHNORR-ZKP-Verify: Disable\n" );
00214 #endif
00215      return -1;
00216    }
00217    //----------------------------------------------------------------------
00218    template<typename OsModel_P,
00219             typename Radio_P,
00220             typename Debug_P>
00221    void
00222    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00223 	key_setup( Point *pubkey ) {
00224 
00225 #ifdef ENABLE_SCHNORRZKP_DEBUG
00226       debug().debug("Debug::Start Schnorr Interactive ZKP Verifier on::%d \n", radio().id() );
00227 #endif
00228       success_rounds=0;
00229       required_rounds = REQ_ROUNDS;
00230 
00231       //copy keys to local variables
00232       //public key available to prover and verifier
00233       eccfp.p_clear(&B);
00234       eccfp.p_copy(&B, pubkey);
00235    }
00236 
00237    //------------------------------------------------------------------------------------
00238    template<typename OsModel_P,
00239                typename Radio_P,
00240                typename Debug_P>
00241    void
00242    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00243 	compute_hash(){
00244 #ifdef ENABLE_SCHNORRZKP_DEBUG
00245       debug().debug("Debug::Starting computing the hash on the point received by prover!\n", radio().id() );
00246 #endif
00247 
00248       //task for the verifier to compute the hash c
00249       //c = HASH( G, B, A)
00250       block_data_t input[6*(KEYDIGITS*NN_DIGIT_LEN + 1)];
00251       block_data_t b[20];
00252       //convert point G to octet and place to input
00253       eccfp.point2octet(input, 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &param.G, FALSE);
00254       //convert point B to octet and place to input
00255       eccfp.point2octet(input + 2*(KEYDIGITS*NN_DIGIT_LEN + 1), 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &B, FALSE);
00256       //convert point A to octet and place to input
00257       eccfp.point2octet(input + 4*(KEYDIGITS*NN_DIGIT_LEN + 1), 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &A, FALSE);
00258 
00259       //digest
00260       SHA1Context sha;
00261       SHA1::SHA1Reset(&sha);
00262       SHA1::SHA1Update(&sha, input, 6*(KEYDIGITS*NN_DIGIT_LEN + 1));
00263       SHA1::SHA1Digest(&sha, b);
00264 
00265       //place the hash on a private key
00266       NN_DIGIT key[NUMWORDS];
00267       pmp.AssignZero(key, NUMWORDS);
00268       //decode the private key received
00269       pmp.Decode(key, NUMWORDS, b, 20);
00270 
00271       //mod n the hash output
00272       pmp.Mod(c, key, NUMWORDS, param.r, NUMWORDS);
00273 
00274       //convert c to octet, place c to buffer
00275       //and send the hash c to the prover
00276       block_data_t buffer[KEYDIGITS * NN_DIGIT_LEN +2];
00277       buffer[0]=HASH_MSG;
00278       pmp.Encode(buffer+1, KEYDIGITS * NN_DIGIT_LEN +1, c, NUMWORDS);
00279 
00280 #ifdef ENABLE_SCHNORRZKP_DEBUG
00281       debug().debug("Debug::Finished hash calculation!Sending the hash to prover. ::%d \n", radio().id() );
00282 #endif
00283       radio().send(Radio::BROADCAST_ADDRESS, KEYDIGITS * NN_DIGIT_LEN +2 , buffer);
00284    }
00285 
00286    //------------------------------------------------------------------------------------
00287    template<typename OsModel_P,
00288             typename Radio_P,
00289             typename Debug_P>
00290    void
00291    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00292 	verify(){
00293 #ifdef ENABLE_SCHNORRZKP_DEBUG
00294       debug().debug("Debug::Starting Verify!\n", radio().id() );
00295 #endif
00296       //verifier checks that A + cB = xG
00297       Point result;
00298       Point result1;
00299       eccfp.p_clear(&result);
00300       eccfp.p_clear(&result1);
00301       eccfp.p_clear(&P);
00302 
00303       //compute xG
00304       eccfp.gen_public_key(&result, Valid);
00305 
00306       //compute cB
00307       eccfp.c_mul(&result1, &B, c);
00308 
00309       //compute A + cB
00310       eccfp.c_add_affine(&P, &result1, &A);
00311 
00312       //is the result correct???
00313       //compare point A with point P
00314       if(eccfp.p_equal(&result,&P)==true)
00315       {
00316          success_rounds++;
00317 #ifdef ENABLE_SCHNORRZKP_DEBUG
00318          debug().debug("Debug::Check SUCCESS!\n", radio().id() );
00319 #endif
00320       }
00321       else
00322       {
00323 #ifdef ENABLE_SCHNORRZKP_DEBUG
00324          debug().debug( "Debug::Check FAIL!\n", radio().id() );
00325 #endif
00326       }
00327 
00328       //call the task final decision
00329       final_decision();
00330    }
00331 
00332    //----------------------------------------------------------------------------------------
00333    template<typename OsModel_P,
00334             typename Radio_P,
00335             typename Debug_P>
00336    void
00337    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00338 	final_decision(){
00339 
00340       //were the round successful??the protocol accepts
00341       if(success_rounds==required_rounds)
00342       {
00343 #ifdef ENABLE_SCHNORRZKP_DEBUG
00344          debug().debug("Debug::Protocol finished with success.Secret Verified!!Prover HONEST!\n", radio().id() );
00345 #endif
00346          //send to prover the accept message
00347          block_data_t buffer[1];
00348          buffer[0]=ACCEPT_MSG;
00349          radio().send(Radio::BROADCAST_ADDRESS, 1, buffer);
00350       }
00351       //the round failed, the protocol rejects
00352       else
00353       {
00354 #ifdef ENABLE_SCHNORRZKP_DEBUG
00355          debug().debug("Debug::Protocol finished without success.Secret NOT Verified!!Prover NOT HONEST\n", radio().id() );
00356 #endif
00357          block_data_t buffer[1];
00358          buffer[0]=REJECT_MSG;
00359          radio().send(Radio::BROADCAST_ADDRESS, 1, buffer);
00360       }
00361    }
00362 
00363    //---------------------------------------------------------------------------
00364    template<typename OsModel_P,
00365             typename Radio_P,
00366             typename Debug_P>
00367    void
00368    SCHNORRZKPVerify<OsModel_P, Radio_P, Debug_P>::
00369 	receive( node_id_t from, size_t len, block_data_t *data ) {
00370 
00371       if( from == radio().id() ) return;
00372 
00373       if(data[0]==START_MSG)
00374       {
00375 #ifdef ENABLE_SCHNORRZKP_DEBUG
00376          debug().debug("Debug::Received a starting message::%d \n", radio().id() );
00377 #endif
00378 
00379          //get Verify point A from the message
00380          eccfp.p_clear(&A);
00381 
00382          //convert octet received to point A
00383          eccfp.octet2point(&A, data+1, 2*(KEYDIGITS * NN_DIGIT_LEN +1));
00384 
00385          //call the task to compute hash
00386          compute_hash();
00387       }
00388 
00389       if(data[0]==CONT_MSG)
00390       {
00391 #ifdef ENABLE_SCHNORRZKP_DEBUG
00392          debug().debug("Debug::Received a continue message::%d \n", radio().id() );
00393 #endif
00394 
00395          //get private key x and place to Valid
00396          pmp.AssignZero(Valid, NUMWORDS);
00397          //decode the private key received
00398          pmp.Decode(Valid, NUMWORDS, data+1, KEYDIGITS * NN_DIGIT_LEN +1);
00399 
00400          //call the task for verification
00401          verify();
00402       }
00403 
00404    }
00405 
00406 } //end of wiselib namespace
00407 
00408 #endif /* SCNORRZKP_VERIFIER_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines