Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

jacobi.cc

00001 /*
00002  * Copyright 2003 Michael A. Marsh, Cornell University. All rights reserved.
00003  * This software is released under the modified BSD license.
00004  * See the file LICENSE in the top-level directory for details.
00005  */
00006 //
00007 // $Id: jacobi.cc,v 1.3 2004/05/19 15:56:48 mmarsh Exp $
00008 //
00009 // $Log: jacobi.cc,v $
00010 // Revision 1.3  2004/05/19 15:56:48  mmarsh
00011 // *** empty log message ***
00012 //
00013 // Revision 1.2  2003/11/04 22:31:48  mmarsh
00014 // *** empty log message ***
00015 //
00016 //
00017 
00018 #include "jacobi.h"
00019 #include "CODEX_Exceptions/BignumExceptions.h"
00020 
00021 using namespace CODEX_Ciphers;
00022 
00023 BIGNUM *
00024 CODEX_Ciphers::jacobi( const BIGNUM * a, const BIGNUM * n )
00025 {
00026    static BIGNUM * zero     = 0;
00027    static BIGNUM * one      = 0;
00028    static BIGNUM * minusOne = 0;
00029    static BIGNUM * three    = 0;
00030    static BIGNUM * four     = 0;
00031    static BIGNUM * five     = 0;
00032    static BIGNUM * seven    = 0;
00033    static BIGNUM * eight    = 0;
00034 
00035    // Set up the constants we'll need.
00036    if ( 0 == zero )
00037    {
00038       zero = BN_new();
00039       if ( 0 == zero )
00040       {
00041          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00042       }
00043       if ( ! BN_zero( zero ) )
00044       {
00045          BN_free( zero );
00046          zero = 0;
00047          throw CODEX_Exceptions::BignumSetWordException( __FILE__ , __LINE__ );
00048       }
00049    }
00050 
00051    if ( 0 == one )
00052    {
00053       one = BN_new();
00054       if ( 0 == one )
00055       {
00056          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00057       }
00058       if ( ! BN_one( one ) )
00059       {
00060          BN_free( one );
00061          one = 0;
00062          throw CODEX_Exceptions::BignumSetWordException( __FILE__ , __LINE__ );
00063       }
00064    }
00065 
00066    if ( 0 == minusOne )
00067    {
00068       minusOne = BN_new();
00069       if ( 0 == minusOne )
00070       {
00071          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00072       }
00073       if ( ! BN_sub( minusOne, zero, one ) )
00074       {
00075          BN_free( minusOne );
00076          minusOne = 0;
00077          throw CODEX_Exceptions::BignumSubException( __FILE__ , __LINE__ );
00078       }
00079    }
00080 
00081    if ( 0 == four )
00082    {
00083       four = BN_new();
00084       if ( 0 == four )
00085       {
00086          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00087       }
00088       if ( ! BN_lshift( four, one, 2 ) )
00089       {
00090          BN_free( four );
00091          four = 0;
00092          throw CODEX_Exceptions::BignumLshiftException( __FILE__ , __LINE__ );
00093       }
00094    }
00095 
00096    if ( 0 == three )
00097    {
00098       three = BN_new();
00099       if ( 0 == three )
00100       {
00101          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00102       }
00103       if ( ! BN_sub( three, four, one ) )
00104       {
00105          BN_free( three );
00106          three = 0;
00107          throw CODEX_Exceptions::BignumSubException( __FILE__ , __LINE__ );
00108       }
00109    }
00110 
00111    if ( 0 == five )
00112    {
00113       five = BN_new();
00114       if ( 0 == five )
00115       {
00116          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00117       }
00118       if ( ! BN_add( five, four, one ) )
00119       {
00120          BN_free( five );
00121          five = 0;
00122          throw CODEX_Exceptions::BignumAddException( __FILE__ , __LINE__ );
00123       }
00124    }
00125 
00126    if ( 0 == seven )
00127    {
00128       seven = BN_new();
00129       if ( 0 == seven )
00130       {
00131          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00132       }
00133       if ( ! BN_add( seven, four, three ) )
00134       {
00135          BN_free( seven );
00136          seven = 0;
00137          throw CODEX_Exceptions::BignumAddException( __FILE__ , __LINE__ );
00138       }
00139    }
00140 
00141    if ( 0 == eight )
00142    {
00143       eight = BN_new();
00144       if ( 0 == eight )
00145       {
00146          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00147       }
00148       if ( ! BN_lshift( eight, one, 3 ) )
00149       {
00150          BN_free( eight );
00151          eight = 0;
00152          throw CODEX_Exceptions::BignumLshiftException( __FILE__ , __LINE__ );
00153       }
00154    }
00155 
00156    // Now the algorithm
00157    if ( 0 == BN_cmp( a, zero ) )
00158    {
00159       return BN_dup( zero );
00160    }
00161    if ( 0 == BN_cmp( a, one ) )
00162    {
00163       return BN_dup( one );
00164    }
00165 
00166    // Simple tests on inputs
00167    if ( BN_cmp( n, three ) < 0 )
00168    {
00169       return 0;
00170    }
00171    if ( ! BN_is_odd( n ) )
00172    {
00173       return 0;
00174    }
00175    if ( BN_cmp( a, zero ) < 0 )
00176    {
00177       return 0;
00178    }
00179    if ( BN_cmp( a, n ) >= 0 )
00180    {
00181       return 0;
00182    }
00183 
00184    BIGNUM * a1   = 0;
00185    BIGNUM * n1   = 0;
00186    BIGNUM * s    = 0;
00187    BIGNUM * temp = 0;
00188    BN_CTX * ctx  = 0;
00189    try
00190    {
00191       ctx = BN_CTX_new();
00192       if ( 0 == ctx )
00193       {
00194          throw CODEX_Exceptions::BignumContextException( __FILE__ , __LINE__ );
00195       }
00196 
00197       temp = BN_new();
00198       if ( 0 == temp )
00199       {
00200          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00201       }
00202 
00203       unsigned long e = 0;
00204       a1 = BN_dup( a );
00205       if ( 0 == a1 )
00206       {
00207          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00208       }
00209       while ( ! BN_is_odd( a1 ) )
00210       {
00211          if ( ! BN_rshift( a1, a1, 1 ) )
00212          {
00213             throw CODEX_Exceptions::BignumRshiftException( __FILE__ ,
00214                                                            __LINE__ );
00215          }
00216          ++e;
00217       }
00218 
00219       if ( 0 == (e%2) )
00220       {
00221          s = BN_dup( one );
00222       }
00223       else
00224       {
00225          if ( ! BN_mod( temp, n, eight, ctx ) )
00226          {
00227             throw CODEX_Exceptions::BignumModException( __FILE__ , __LINE__ );
00228          }
00229 
00230          if ( ( 0 == BN_cmp( temp, one ) ) ||
00231               ( 0 == BN_cmp( temp, seven ) ) )
00232          {
00233             s = BN_dup( one );
00234          }
00235          else
00236          {
00237             s = BN_dup( minusOne );
00238          }
00239       }
00240 
00241       if ( ! BN_mod( temp, n, four, ctx ) )
00242       {
00243          throw CODEX_Exceptions::BignumModException( __FILE__ , __LINE__ );
00244       }
00245       if ( 0 == BN_cmp( temp, three ) )
00246       {
00247          if ( ! BN_mod( temp, a1, four, ctx ) )
00248          {
00249             throw CODEX_Exceptions::BignumModException( __FILE__ , __LINE__ );
00250          }
00251          if ( 0 == BN_cmp( temp, three ) )
00252          {
00253             if ( ! BN_sub( s, zero, s ) )
00254             {
00255                throw CODEX_Exceptions::BignumSubException( __FILE__ ,
00256                                                            __LINE__ );
00257             }
00258          }
00259       }
00260       BN_free(temp);  temp = 0;
00261 
00262       BIGNUM * retVal;
00263       if ( 0 == BN_cmp( a1, one ) )
00264       {
00265          retVal = BN_dup( one );
00266       }
00267       else
00268       {
00269          n1 = BN_new();
00270          if ( 0 == n1 )
00271          {
00272             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00273          }
00274          if ( ! BN_mod( n1, n, a1, ctx ) )
00275          {
00276             throw CODEX_Exceptions::BignumModException( __FILE__ , __LINE__ );
00277          }
00278          temp = jacobi( n1, a1 );
00279          if ( 0 == temp )
00280          {
00281             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00282          }
00283          if ( ! BN_mul( s, s, temp, ctx ) )
00284          {
00285             throw CODEX_Exceptions::BignumMulException( __FILE__ , __LINE__ );
00286          }
00287          retVal = BN_dup( s );
00288       }
00289 
00290       BN_CTX_free( ctx );
00291       BN_free( temp );
00292       BN_free( a1 );
00293       BN_free( n1 );
00294       BN_free( s );
00295 
00296       return retVal;
00297    }
00298    catch ( ... )
00299    {
00300       if ( 0 != a1   ) BN_free( a1 );
00301       if ( 0 != n1   ) BN_free( n1 );
00302       if ( 0 != s    ) BN_free( s );
00303       if ( 0 != temp ) BN_free( temp );
00304       if ( 0 != ctx  ) BN_CTX_free( ctx );
00305       throw;
00306    }
00307 }
00308 

Generated on Fri May 6 17:39:58 2005 for COrnell Data EXchange (CODEX) by  doxygen 1.4.1