Wiselib
|
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_SCHNORRZKP_PROVER_H_ 00021 #define __ALGORITHMS_CRYPTO_SHCNORRZKP_PROVER_H_ 00022 00023 00024 #include "algorithms/crypto/eccfp.h" 00025 #include <string.h> 00026 00027 //Uncomment to enable Debug 00028 #define ENABLE_SCHNORRZKP_DEBUG 00029 00030 /* PROTOCOL DESCRIPTION 00031 00032 Schnorr's Protocol 00033 00034 Prover and Verifier agree on an elliptic curve E over a field Fn , a generator 00035 G in E/Fn . They both know B in E/Fn and Prover claims he knows x such 00036 that B = x * G. 00037 00038 Protocol Steps 00039 00040 1. Prover generates random r and computes A = r * G 00041 2. Prover sends A to Verifier 00042 3. Verifier computes c = HASH(G, B, A) and sends c to Prover 00043 4. Prover computes m = r + cx and sends m to Verifier 00044 5 Verifier checks that P = m*G-c*B =(r+cx)*G-c*B = r*G+cx*G - c*xG = A 00045 and that HASH(G, B, P ) = c. 00046 */ 00047 00048 namespace wiselib { 00049 00050 template<typename OsModel_P, typename Radio_P = typename OsModel_P::Radio, typename Debug_P = typename OsModel_P::Debug> 00051 class SCHNORRZKPProve 00052 { 00053 public: 00054 typedef OsModel_P OsModel; 00055 typedef Radio_P Radio; 00056 typedef Debug_P Debug; 00057 00058 typedef SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P> self_t; 00059 typedef typename Radio::node_id_t node_id_t; 00060 typedef typename Radio::size_t size_t; 00061 typedef typename Radio::block_data_t block_data_t; 00062 typedef self_t* self_pointer_t; 00063 00066 SCHNORRZKPProve(); 00067 ~SCHNORRZKPProve(); 00069 00070 int init( Radio& radio, Debug& debug ) 00071 { 00072 radio_ = &radio; 00073 debug_ = &debug; 00074 return 0; 00075 } 00076 00080 00081 inline int init(); 00082 inline int destruct(); 00083 00084 int enable_radio( void ); 00085 int disable_radio( void ); 00086 00087 //message types 00088 enum MsgHeaders { 00089 START_MSG = 200, 00090 HASH_MSG = 201, 00091 CONT_MSG = 202, 00092 ACCEPT_MSG = 203, 00093 REJECT_MSG = 204 00094 }; 00095 00097 void key_setup(NN_DIGIT *privkey , Point *pubkey); 00098 void start_proof(); 00099 void send_key(); 00100 00101 protected: 00102 void receive( node_id_t from, size_t len, block_data_t *data ); 00103 00104 private: 00105 00106 Radio& radio() 00107 { return *radio_; } 00108 00109 Debug& debug() 00110 { return *debug_; } 00111 00112 typename Radio::self_pointer_t radio_; 00113 typename Debug::self_pointer_t debug_; 00114 00115 //necessary class objects 00116 ECCFP eccfp; 00117 PMP pmp; 00118 00119 //rounds of the protocol used for seeding the rand function 00120 uint16_t rounds; 00121 00122 //private key that only the prover knows 00123 NN_DIGIT m[NUMWORDS]; 00124 00125 //public key that both prover and verifier know 00126 Point B; 00127 00128 //private key r that is generated in every round and 00129 //its corresponding public key 00130 NN_DIGIT r[NUMWORDS]; 00131 Point Verify; 00132 00133 //the hash that will be received from verifier 00134 NN_DIGIT Hash[NUMWORDS]; 00135 00136 //data that will be sent to the verifier 00137 NN_DIGIT x[NUMWORDS]; 00138 00139 }; 00140 00141 // ----------------------------------------------------------------------- 00142 template<typename OsModel_P, 00143 typename Radio_P, 00144 typename Debug_P> 00145 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00146 SCHNORRZKPProve() 00147 :radio_(0), 00148 debug_(0) 00149 {} 00150 00151 // ----------------------------------------------------------------------- 00152 template<typename OsModel_P, 00153 typename Radio_P, 00154 typename Debug_P> 00155 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00156 ~SCHNORRZKPProve() 00157 {} 00158 //----------------------------------------------------------------------- 00159 template<typename OsModel_P, 00160 typename Radio_P, 00161 typename Debug_P> 00162 int 00163 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00164 init( void ) 00165 { 00166 enable_radio(); 00167 return 0; 00168 } 00169 //----------------------------------------------------------------------------- 00170 template<typename OsModel_P, 00171 typename Radio_P, 00172 typename Debug_P> 00173 int 00174 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00175 destruct( void ) 00176 { 00177 return disable_radio(); 00178 } 00179 //--------------------------------------------------------------------------- 00180 template<typename OsModel_P, 00181 typename Radio_P, 00182 typename Debug_P> 00183 int 00184 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00185 enable_radio( void ) 00186 { 00187 #ifdef ENABLE_SCHNORRZKP_DEBUG 00188 debug().debug( "Debug::SCHNORR-ZKPProve: Boot for %i\n", radio().id() ); 00189 #endif 00190 00191 radio().enable_radio(); 00192 radio().template reg_recv_callback<self_t, &self_t::receive>( this ); 00193 00194 return 0; 00195 } 00196 //--------------------------------------------------------------------------- 00197 template<typename OsModel_P, 00198 typename Radio_P, 00199 typename Debug_P> 00200 int 00201 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00202 disable_radio( void ) 00203 { 00204 #ifdef ENABLE_SCHNORRZKP_DEBUG 00205 debug().debug( "SCHNORR-ZKPProve: Disable\n" ); 00206 #endif 00207 return -1; 00208 } 00209 //----------------------------------------------------------------------- 00210 template<typename OsModel_P, 00211 typename Radio_P, 00212 typename Debug_P> 00213 void 00214 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00215 key_setup( NN_DIGIT *privkey , Point *pubkey ) { 00216 00217 rounds=1; 00218 00219 //copy the keys to the local variables 00220 pmp.AssignZero(m, NUMWORDS); 00221 pmp.Assign(m, privkey, NUMWORDS); 00222 00223 //public key available to prover and verifier 00224 eccfp.p_clear(&B); 00225 eccfp.p_copy(&B, pubkey); 00226 } 00227 00228 //--------------------------------------------------------------------------- 00229 template<typename OsModel_P, 00230 typename Radio_P, 00231 typename Debug_P> 00232 void 00233 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00234 start_proof( void ) { 00235 00236 #ifdef ENABLE_SCHNORRZKP_DEBUG 00237 debug().debug("Debug::Starting Schnorr Interactive ZKP Prover on::%d \n", radio().id() ); 00238 #endif 00239 00240 //if the protocol is booting generate random r and compute A=rG 00241 //and send A to verifier 00242 rounds++; 00243 00244 //clear private and public key 00245 pmp.AssignZero(r, NUMWORDS); 00246 eccfp.p_clear(&Verify); 00247 00248 #ifdef ENABLE_SCHNORRZKP_DEBUG 00249 debug().debug("Debug::Generating random r and compute A=rG. ::%d \n", radio().id() ); 00250 #endif 00251 00252 //generate random r and compute pubKey A=rG 00253 eccfp.gen_private_key(r, rounds); 00254 eccfp.gen_public_key(&Verify, r); 00255 00256 //place the verify key in the buffer and send the message 00257 block_data_t msg[2*(KEYDIGITS*NN_DIGIT_LEN + 1) + 1]; 00258 msg[0]=START_MSG; 00259 00260 //convert point to octet 00261 eccfp.point2octet(msg+1, 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &Verify, FALSE); 00262 00263 #ifdef ENABLE_SCHNORRZKP_DEBUG 00264 debug().debug("Debug::Finished calculations!Sending verify key to verifier. ::%d \n", radio().id() ); 00265 #endif 00266 radio().send(Radio::BROADCAST_ADDRESS, 2*(KEYDIGITS*NN_DIGIT_LEN + 1) +1, msg); 00267 } 00268 00269 //------------------------------------------------------------------------ 00270 template<typename OsModel_P, 00271 typename Radio_P, 00272 typename Debug_P> 00273 void 00274 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00275 send_key( void ) { 00276 00277 #ifdef ENABLE_SCHNORRZKP_DEBUG 00278 debug().debug("Debug::Creating the new private key ::%d \n", radio().id() ); 00279 #endif 00280 00281 //prover computes x= r + cm 00282 //and sends x to verifier 00283 00284 //clear private key x 00285 pmp.AssignZero(x, NUMWORDS); 00286 00287 NN_DIGIT mid2[NUMWORDS]; 00288 pmp.AssignZero(mid2, NUMWORDS); 00289 00290 //first compute cm 00291 pmp.ModMult(mid2, Hash, m, param.r, NUMWORDS); 00292 //then add r+cm 00293 pmp.ModAdd(x, r, mid2, param.r, NUMWORDS); 00294 00295 //send the message with x to verifier 00296 //if it is tails send to verifier m+r 00297 block_data_t buffer[KEYDIGITS*NN_DIGIT_LEN + 2]; 00298 buffer[0]=CONT_MSG; 00299 00300 //convert x to octet 00301 pmp.Encode(buffer+1, KEYDIGITS * NN_DIGIT_LEN +1, x, NUMWORDS); 00302 00303 #ifdef ENABLE_SCHNORRZKP_DEBUG 00304 debug().debug("Debug::Sending the new private key x to verifier::%d \n", radio().id() ); 00305 #endif 00306 radio().send(Radio::BROADCAST_ADDRESS, KEYDIGITS*NN_DIGIT_LEN +2 , buffer); 00307 } 00308 00309 //--------------------------------------------------------------------------- 00310 template<typename OsModel_P, 00311 typename Radio_P, 00312 typename Debug_P> 00313 void 00314 SCHNORRZKPProve<OsModel_P, Radio_P, Debug_P>:: 00315 receive( node_id_t from, size_t len, block_data_t *data ) { 00316 00317 if( from == radio().id() ) return; 00318 00319 if(data[0]==HASH_MSG) 00320 { 00321 00322 #ifdef ENABLE_SCHNORRZKP_DEBUG 00323 debug().debug("Debug::Received a hash message. Calling the send_key task.::%d \n", radio().id() ); 00324 #endif 00325 00326 //clear the private key and store it 00327 pmp.AssignZero(Hash, NUMWORDS); 00328 //decode the private key received 00329 pmp.Decode(Hash, NUMWORDS, data+1, KEYDIGITS * NN_DIGIT_LEN +1); 00330 00331 //calling the send_key task 00332 send_key(); 00333 } 00334 00335 if(data[0]==ACCEPT_MSG) 00336 { 00337 #ifdef ENABLE_SCHNORRZKP_DEBUG 00338 debug().debug("Debug::I got ACCEPTED from the verifier.YESSS!::%d \n", radio().id() ); 00339 #endif 00340 } 00341 00342 if(data[0]==REJECT_MSG) 00343 { 00344 #ifdef ENABLE_SCHNORRZKP_DEBUG 00345 debug().debug("Debug::I got REJECTED from the verifier.NOOO!::%d \n", radio().id() ); 00346 #endif 00347 } 00348 00349 } 00350 00351 } //end of wiselib namespace 00352 00353 #endif /* SCHNORRZKP_PROVER_H_ */