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