Wiselib
wiselib.testing/algorithms/crypto/ecdsafp.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines