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_ECDSA_H_ 00021 #define __ALGORITHMS_CRYPTO_ECDSA_H_ 00022 00023 #include "algorithms/crypto/eccfp.h" 00024 #include "algorithms/crypto/sha1.h" 00025 #include <string.h> 00026 00027 namespace wiselib 00028 { 00039 template<typename OsModel_P> 00040 class ECDSA 00041 { 00042 public: 00043 typedef OsModel_P OsModel; 00044 00047 ECDSA(); 00048 ~ECDSA(); 00050 00053 void enable( void ); 00054 void disable( void ); 00056 00061 void sign(uint8_t *msg, uint8_t len, NN_DIGIT *r, NN_DIGIT *s, NN_DIGIT *d); 00062 uint8_t verify(uint8_t *msg, uint8_t len, NN_DIGIT *r, NN_DIGIT *s, Point *Q); 00063 00064 //initialize a random seed for private key generation 00065 void key_setup(uint8_t seed); 00066 00067 private: 00068 //objects for necessary classes 00069 ECCFP eccfp; 00070 PMP pmp; 00071 uint8_t seed1; 00072 }; 00073 00074 // ----------------------------------------------------------------------- 00075 template<typename OsModel_P> 00076 ECDSA<OsModel_P>:: 00077 ECDSA() 00078 {} 00079 // ----------------------------------------------------------------------- 00080 template<typename OsModel_P> 00081 ECDSA<OsModel_P>:: 00082 ~ECDSA() 00083 {} 00084 // ----------------------------------------------------------------------- 00085 template<typename OsModel_P> 00086 void 00087 ECDSA<OsModel_P>:: 00088 enable( void ) 00089 { 00090 } 00091 // ----------------------------------------------------------------------- 00092 template<typename OsModel_P> 00093 void 00094 ECDSA<OsModel_P>:: 00095 disable( void ) 00096 { 00097 00098 } 00099 //---------------------------------------------------------------------------- 00100 template<typename OsModel_P> 00101 void 00102 ECDSA<OsModel_P>:: 00103 sign(uint8_t *msg, uint8_t len, NN_DIGIT *r, NN_DIGIT *s, NN_DIGIT *d) 00104 { 00105 bool done = FALSE; 00106 NN_DIGIT k[NUMWORDS]; 00107 NN_DIGIT k_inv[NUMWORDS]; 00108 NN_DIGIT tmp[NUMWORDS]; 00109 NN_DIGIT digest[NUMWORDS]; 00110 00111 Point P; 00112 eccfp.p_clear(&P); 00113 uint8_t sha1sum[20]; 00114 NN_DIGIT sha1tmp[20/NN_DIGIT_LEN]; 00115 SHA1Context ctx; 00116 NN_UINT result_bit_len, order_bit_len; 00117 00118 while(!done) 00119 { 00120 //generate private key k 00121 eccfp.gen_private_key(k, seed1); 00122 00123 if (( pmp.Zero(k, NUMWORDS)) == 1) 00124 continue; 00125 00126 //compute the public key kG = (x1, y1) 00127 eccfp.gen_public_key(&P, k); 00128 00129 //compute r = x1 modn 00130 pmp.Mod(r, P.x, NUMWORDS, param.r, NUMWORDS); 00131 00132 if ((pmp.Zero(r, NUMWORDS)) == 1) 00133 continue; 00134 00135 //compute k^{-1} modn 00136 pmp.ModInv(k_inv, k, param.r, NUMWORDS); 00137 00138 //compute hash of message m 00139 memset(sha1sum, 0, 20); 00140 memset(digest, 0, NUMWORDS*NN_DIGIT_LEN); 00141 SHA1::SHA1Reset(&ctx); 00142 SHA1::SHA1Update(&ctx, msg, len); 00143 SHA1::SHA1Digest(&ctx, sha1sum); 00144 00145 //convert hash to an integer 00146 pmp.Decode(sha1tmp, 20/NN_DIGIT_LEN, sha1sum, 20); 00147 00148 result_bit_len = pmp.Bits(sha1tmp, 20/NN_DIGIT_LEN); 00149 order_bit_len = pmp.Bits(param.r, NUMWORDS); 00150 if(result_bit_len > order_bit_len) 00151 { 00152 pmp.Mod(digest, sha1tmp, 20/NN_DIGIT_LEN, param.r, NUMWORDS); 00153 } 00154 else 00155 { 00156 memset(digest, 0, NUMWORDS*NN_DIGIT_LEN); 00157 pmp.Assign(digest, sha1tmp, 20/NN_DIGIT_LEN); 00158 if(result_bit_len == order_bit_len) 00159 pmp.ModSmall(digest, param.r, NUMWORDS); 00160 } 00161 //compute s= k^{-1} * (e + dr) 00162 pmp.ModMult(k, d, r, param.r, NUMWORDS); 00163 pmp.ModAdd(tmp, digest, k, param.r, NUMWORDS); 00164 pmp.ModMult(s, k_inv, tmp, param.r, NUMWORDS); 00165 if ((pmp.Zero(s, NUMWORDS)) != 1) 00166 done = TRUE; 00167 } 00168 } 00169 //------------------------------------------------------------------------------ 00170 template<typename OsModel_P> 00171 uint8_t 00172 ECDSA<OsModel_P>:: 00173 verify(uint8_t *msg, uint8_t len, NN_DIGIT *r, NN_DIGIT *s, Point *Q) 00174 { 00175 uint8_t sha1sum[20]; 00176 NN_DIGIT sha1tmp[20/NN_DIGIT_LEN]; 00177 SHA1Context ctx; 00178 NN_DIGIT w[NUMWORDS]; 00179 NN_DIGIT u1[NUMWORDS]; 00180 NN_DIGIT u2[NUMWORDS]; 00181 NN_DIGIT digest[NUMWORDS]; 00182 NN_UINT result_bit_len, order_bit_len; 00183 00184 Point u1P; 00185 Point u2Q; 00186 eccfp.p_clear(&u1P); 00187 eccfp.p_clear(&u2Q); 00188 00189 Point final; 00190 eccfp.p_clear(&final); 00191 00192 //check if r and s are in [1, p-1] 00193 if ((pmp.Cmp(r, param.r, NUMWORDS)) >= 0) 00194 return 3; 00195 if ((pmp.Zero(r, NUMWORDS)) == 1) 00196 return 4; 00197 if ((pmp.Cmp(s, param.r, NUMWORDS)) >= 0) 00198 return 5; 00199 if ((pmp.Zero(s, NUMWORDS)) == 1) 00200 return 6; 00201 00202 //compute w = s^-1 mod p 00203 pmp.ModInv(w, s, param.r, NUMWORDS); 00204 00205 //compute the hash of the message 00206 memset(sha1sum, 0, 20); 00207 memset(digest, 0, NUMWORDS*NN_DIGIT_LEN); 00208 SHA1::SHA1Reset(&ctx); 00209 SHA1::SHA1Update(&ctx, msg, len); 00210 SHA1::SHA1Digest(&ctx, sha1sum); 00211 00212 //convert hash to an integer 00213 pmp.Decode(sha1tmp, 20/NN_DIGIT_LEN, sha1sum, 20); 00214 result_bit_len = pmp.Bits(sha1tmp, 20/NN_DIGIT_LEN); 00215 order_bit_len = pmp.Bits(param.r, NUMWORDS); 00216 if(result_bit_len > order_bit_len) 00217 { 00218 pmp.Mod(digest, sha1tmp, 20/NN_DIGIT_LEN, param.r, NUMWORDS); 00219 } 00220 else 00221 { 00222 pmp.Assign(digest, sha1tmp, 20/NN_DIGIT_LEN); 00223 if(result_bit_len == order_bit_len) 00224 pmp.ModSmall(digest, param.r, NUMWORDS); 00225 } 00226 00227 //compute u1 = HASH * w mod p 00228 pmp.ModMult(u1, digest, w, param.r, NUMWORDS); 00229 //compute u2 = r *w mod p 00230 pmp.ModMult(u2, r, w, param.r, NUMWORDS); 00231 00232 //compute u1G + u2Q 00233 eccfp.c_mul(&u1P, &(param.G), u1); //u1*G 00234 eccfp.c_mul(&u2Q, Q, u2); //u2*Q 00235 eccfp.c_add_affine(&final, &u1P, &u2Q); 00236 00237 result_bit_len = pmp.Bits(final.x, NUMWORDS); 00238 order_bit_len = pmp.Bits(param.r, NUMWORDS); 00239 if(result_bit_len > order_bit_len) 00240 { 00241 pmp.Mod(w, final.x, NUMWORDS, param.r, NUMWORDS); 00242 } 00243 else 00244 { 00245 pmp.Assign(w, final.x, NUMWORDS); 00246 if(result_bit_len == order_bit_len) 00247 pmp.ModSmall(w, param.r, NUMWORDS); 00248 } 00249 00250 if ((pmp.Cmp(w, r, NUMWORDS)) == 0) 00251 { 00252 //accept signature 00253 return 1; 00254 } 00255 else 00256 { 00257 //reject signature 00258 return 2; 00259 } 00260 } 00261 //------------------------------------------------------------------------------ 00262 template<typename OsModel_P> 00263 void 00264 ECDSA<OsModel_P>:: 00265 key_setup(uint8_t seed) 00266 { 00267 //initialize random seed 00268 seed1 = seed; 00269 } 00270 00271 00272 } //end of namespace wiselib 00273 00274 #endif