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_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), ¶m.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_ */