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_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_ */