00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
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
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