1 /** 2 * Unit test helper 3 * 4 * Copyright: 5 * (C) 2014-2015 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.math.ec_gfp.test; 12 13 import botan.constants; 14 static if (BOTAN_TEST && BOTAN_HAS_PUBLIC_KEY_CRYPTO): 15 16 import botan.test; 17 18 import botan.codec.hex; 19 import botan.rng.auto_rng; 20 import botan.math.numbertheory.numthry; 21 import botan.math.ec_gfp.curve_gfp; 22 import botan.math.ec_gfp.point_gfp; 23 import botan.pubkey.algo.ec_group; 24 import botan.math.numbertheory.reducer; 25 import botan.asn1.oids; 26 import botan.utils.types; 27 import botan.utils.mem_ops; 28 29 size_t total_tests; 30 31 string toString(PointGFp point) { 32 Vector!char output; 33 output ~= "(" ~ point.getAffineX().toString() ~ " " ~ point.getAffineY().toString() ~ " )"; 34 return output[].idup; 35 } 36 37 PointGFp createRandomPoint(RandomNumberGenerator rng, const ref CurveGFp curve) 38 { 39 const BigInt* p = &curve.getP(); 40 41 ModularReducer mod_p = ModularReducer(*p); 42 43 while(true) 44 { 45 BigInt x = BigInt(rng, p.bits()); 46 47 BigInt x3 = mod_p.multiply(x, mod_p.square(x)); 48 49 BigInt ax = mod_p.multiply(curve.getA(), x); 50 51 BigInt bx3 = mod_p.multiply(curve.getB(), x3); 52 53 BigInt y = mod_p.reduce(ax + bx3); 54 55 if (ressol(y, p.dup) > 0) 56 return PointGFp(curve, x, y); 57 } 58 } 59 60 size_t testPointTurnOnSpRedMul() 61 { 62 size_t fails = 0; 63 64 // setting up expected values 65 BigInt exp_Qx = BigInt("466448783855397898016055842232266600516272889280"); 66 BigInt exp_Qy = BigInt("1110706324081757720403272427311003102474457754220"); 67 BigInt exp_Qz = BigInt(1); 68 69 // performing calculation to test 70 string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; 71 string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; 72 string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; 73 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 74 Vector!ubyte sv_p_secp = hexDecode(p_secp); 75 Vector!ubyte sv_a_secp = hexDecode(a_secp); 76 Vector!ubyte sv_b_secp = hexDecode(b_secp); 77 Vector!ubyte sv_G_secp_comp = hexDecode(G_secp_comp); 78 BigInt bi_p_secp = BigInt.decode(sv_p_secp.ptr, sv_p_secp.length); 79 BigInt bi_a_secp = BigInt.decode(sv_a_secp.ptr, sv_a_secp.length); 80 BigInt bi_b_secp = BigInt.decode(sv_b_secp.ptr, sv_b_secp.length); 81 CurveGFp secp160r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 82 PointGFp p_G = OS2ECP(sv_G_secp_comp, secp160r1); 83 84 BigInt d = BigInt("459183204582304"); 85 86 PointGFp r1 = p_G * d; 87 mixin( CHECK(` r1.getAffineX() != 0 `) ); 88 89 PointGFp p_G2 = p_G.dup; 90 91 PointGFp r2 = p_G2 * d; 92 93 mixin( CHECK_MESSAGE( `r1 == r2`, "error with point mul after extra turn on sp red mul" ) ); 94 mixin( CHECK(` r1.getAffineX() != 0 `) ); 95 96 PointGFp p_r1 = r1.dup; 97 PointGFp p_r2 = r2.dup; 98 99 p_r1 *= BigInt(2); 100 p_r2 *= BigInt(2); 101 mixin( CHECK_MESSAGE( `p_r1.getAffineX() == p_r2.getAffineX()`, "error with mult2 after extra turn on sp red mul" ) ); 102 mixin( CHECK(` p_r1.getAffineX() != 0 `) ); 103 mixin( CHECK(` p_r2.getAffineX() != 0 `) ); 104 r1 *= BigInt(2); 105 r2 *= BigInt(2); 106 107 mixin( CHECK_MESSAGE( `r1 == r2`, "error with mult2 after extra turn on sp red mul" ) ); 108 mixin( CHECK_MESSAGE( `r1.getAffineX() == r2.getAffineX()`, "error with mult2 after extra turn on sp red mul" ) ); 109 mixin( CHECK(` r1.getAffineX() != 0 `) ); 110 r1 += p_G; 111 r2 += p_G2; 112 113 mixin( CHECK_MESSAGE( `r1 == r2`, "error with op+= after extra turn on sp red mul" ) ); 114 115 r1 += p_G; 116 r2 += p_G2; 117 118 mixin( CHECK_MESSAGE( `r1 == r2`, "error with op+= after extra turn on sp red mul for both operands" ) ); 119 r1 += p_G; 120 r2 += p_G2; 121 122 mixin( CHECK_MESSAGE( `r1 == r2`, "error with op+= after extra turn on sp red mul for both operands" ) ); 123 return fails; 124 } 125 126 size_t testCoordinates() 127 { 128 size_t fails = 0; 129 130 BigInt exp_affine_x = BigInt("16984103820118642236896513183038186009872590470"); 131 BigInt exp_affine_y = BigInt("1373093393927139016463695321221277758035357890939"); 132 133 // precalculation 134 string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; 135 string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; 136 string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; 137 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 138 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 139 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 140 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 141 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 142 143 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 144 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 145 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 146 CurveGFp secp160r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 147 PointGFp p_G = OS2ECP( sv_G_secp_comp, secp160r1 ); 148 PointGFp p0 = p_G.dup; 149 PointGFp p1 = p_G * BigInt(2); 150 PointGFp point_exp = PointGFp(secp160r1, exp_affine_x, exp_affine_y); 151 if (!point_exp.onTheCurve()) 152 throw new InternalError("Point not on the curve"); 153 154 mixin( CHECK_MESSAGE( `p1.getAffineX() == exp_affine_x`, " p1_x = ` ~ p1.getAffineX().toString() ~ ` \n` ~ `exp_x = ` ~ exp_affine_x.toString() ~ ` \n" ) ); 155 mixin( CHECK_MESSAGE( `p1.getAffineY() == exp_affine_y`, " p1_y = ` ~ p1.getAffineY().toString() ~ ` \n` ~ `exp_y = ` ~ exp_affine_y.toString() ~ ` \n" ) ); 156 return fails; 157 } 158 159 160 /** 161 Test point multiplication according to 162 -------- 163 SEC 2: Test Vectors for SEC 1 164 Certicom Research 165 Working Draft 166 September, 1999 167 Version 0.3; 168 Section 2.1.2 169 -------- 170 */ 171 172 size_t testPointTransformation () 173 { 174 size_t fails = 0; 175 176 // get a vailid point 177 ECGroup dom_pars = ECGroup(OID("1.3.132.0.8")); 178 PointGFp p = dom_pars.getBasePoint().dup; 179 180 // get a copy 181 PointGFp q = p.dup; 182 183 mixin( CHECK_MESSAGE( `p.getAffineX() == q.getAffineX()`, "affine_x changed during copy" ) ); 184 mixin( CHECK_MESSAGE( `p.getAffineY() == q.getAffineY()`, "affine_y changed during copy" ) ); 185 return fails; 186 } 187 188 size_t testPointMult () 189 { 190 size_t fails = 0; 191 192 ECGroup secp160r1 = ECGroup(OIDS.lookup("secp160r1")); 193 194 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 195 Vector!ubyte sv_G_secp_comp = hexDecode(G_secp_comp); 196 PointGFp p_G = OS2ECP(sv_G_secp_comp, secp160r1.getCurve()); 197 198 BigInt d_U = BigInt("0xaa374ffc3ce144e6b073307972cb6d57b2a4e982"); 199 PointGFp Q_U = p_G * d_U; 200 201 mixin( CHECK(` Q_U.getAffineX() == BigInt("466448783855397898016055842232266600516272889280") `) ); 202 mixin( CHECK(` Q_U.getAffineY() == BigInt("1110706324081757720403272427311003102474457754220") `) ); 203 return fails; 204 } 205 206 size_t testPointNegative() 207 { 208 size_t fails = 0; 209 210 // performing calculation to test 211 string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; 212 string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; 213 string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; 214 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 215 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 216 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 217 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 218 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 219 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 220 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 221 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 222 CurveGFp secp160r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 223 PointGFp p_G = OS2ECP( sv_G_secp_comp, secp160r1 ); 224 p_G *= BigInt(2); 225 PointGFp p1 = p_G.dup; 226 227 mixin( CHECK(` p1.getAffineX() == BigInt("16984103820118642236896513183038186009872590470") `) ); 228 mixin( CHECK(` p1.getAffineY() == BigInt("1373093393927139016463695321221277758035357890939") `) ); 229 230 PointGFp p1_neg = p1.negate().dup; 231 232 mixin( CHECK(` p1_neg.getAffineX() == BigInt("16984103820118642236896513183038186009872590470") `) ); 233 mixin( CHECK(` p1_neg.getAffineY() == BigInt("88408243403763901739989511495005261618427168388") `) ); 234 return fails; 235 } 236 237 size_t testZeropoint() 238 { 239 size_t fails = 0; 240 241 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 242 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 243 BigInt bi_p_secp = BigInt("0xffffffffffffffffffffffffffffffff7fffffff"); 244 BigInt bi_a_secp = BigInt("0xffffffffffffffffffffffffffffffff7ffffffc"); 245 BigInt bi_b_secp = BigInt("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); 246 CurveGFp secp160r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 247 auto bi1 = BigInt("16984103820118642236896513183038186009872590470"); 248 auto bi2 = BigInt("1373093393927139016463695321221277758035357890939"); 249 PointGFp p1 = PointGFp(secp160r1, bi1, bi2); 250 251 if (!p1.onTheCurve()) 252 throw new InternalError("Point not on the curve"); 253 p1 -= p1; 254 255 mixin( CHECK_MESSAGE( `p1.isZero()`, "p - q with q = p is not zero!" ) ); 256 return fails; 257 } 258 259 size_t testZeropointEncDec() 260 { 261 size_t fails = 0; 262 263 BigInt bi_p_secp = BigInt("0xffffffffffffffffffffffffffffffff7fffffff"); 264 BigInt bi_a_secp = BigInt("0xffffffffffffffffffffffffffffffff7ffffffc"); 265 BigInt bi_b_secp = BigInt("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); 266 CurveGFp curve = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 267 268 PointGFp p = PointGFp(curve); 269 mixin( CHECK_MESSAGE( `p.isZero()`, "by constructor created zeropoint is no zeropoint!" ) ); 270 271 272 Vector!ubyte sv_p = unlock(EC2OSP(p, PointGFp.UNCOMPRESSED)); 273 PointGFp p_encdec = OS2ECP(sv_p, curve); 274 mixin( CHECK_MESSAGE( `p == p_encdec`, "encoded-decoded (uncompressed) point is not equal the original!" ) ); 275 276 sv_p = unlock(EC2OSP(p, PointGFp.UNCOMPRESSED)); 277 p_encdec = OS2ECP(sv_p, curve); 278 mixin( CHECK_MESSAGE( `p == p_encdec`, "encoded-decoded (compressed) point is not equal the original!" ) ); 279 280 sv_p = unlock(EC2OSP(p, PointGFp.HYBRID)); 281 p_encdec = OS2ECP(sv_p, curve); 282 mixin( CHECK_MESSAGE( `p == p_encdec`, "encoded-decoded (hybrid) point is not equal the original!" ) ); 283 return fails; 284 } 285 286 size_t testCalcWithZeropoint() 287 { 288 size_t fails = 0; 289 290 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 291 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 292 BigInt bi_p_secp = BigInt("0xffffffffffffffffffffffffffffffff7fffffff"); 293 BigInt bi_a_secp = BigInt("0xffffffffffffffffffffffffffffffff7ffffffc"); 294 BigInt bi_b_secp = BigInt("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); 295 CurveGFp curve = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 296 297 auto bi1 = BigInt("16984103820118642236896513183038186009872590470"); 298 auto bi2 = BigInt("1373093393927139016463695321221277758035357890939"); 299 PointGFp p = PointGFp(curve, bi1, bi2); 300 301 if (!p.onTheCurve()) 302 throw new InternalError("Point not on the curve"); 303 mixin( CHECK_MESSAGE( `!p.isZero()`, "created is zeropoint, shouldn't be!" ) ); 304 305 PointGFp zero = PointGFp(curve); 306 mixin( CHECK_MESSAGE( `zero.isZero()`, "by constructor created zeropoint is no zeropoint!" ) ); 307 308 PointGFp res = p + zero; 309 mixin( CHECK_MESSAGE( `res == p`, "point + zeropoint is not equal the point" ) ); 310 311 res = p - zero; 312 mixin( CHECK_MESSAGE( `res == p`, "point - zeropoint is not equal the point" ) ); 313 314 res = zero * BigInt(32432243); 315 mixin( CHECK_MESSAGE( `res.isZero()`, "zeropoint * skalar is not a zero-point!" ) ); 316 return fails; 317 } 318 319 size_t testAddPoint() 320 { 321 size_t fails = 0; 322 323 // precalculation 324 string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; 325 string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; 326 string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; 327 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 328 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 329 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 330 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 331 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 332 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 333 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 334 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 335 CurveGFp secp160r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 336 PointGFp p_G = OS2ECP( sv_G_secp_comp, secp160r1 ); 337 338 PointGFp p0 = p_G.dup; 339 p_G *= BigInt(2); 340 PointGFp p1 = p_G.dup; 341 342 p1 += p0; 343 auto bi1 = BigInt("704859595002530890444080436569091156047721708633"); 344 auto bi2 = BigInt("1147993098458695153857594941635310323215433166682"); 345 PointGFp expected = PointGFp(secp160r1, bi1, bi2); 346 347 mixin( CHECK(` p1 == expected `) ); 348 return fails; 349 } 350 351 size_t testSubPoint() 352 { 353 size_t fails = 0; 354 355 //Setting up expected values 356 BigInt exp_sub_x = BigInt("112913490230515010376958384252467223283065196552"); 357 BigInt exp_sub_y = BigInt("143464803917389475471159193867377888720776527730"); 358 BigInt exp_sub_z = BigInt("562006223742588575209908669014372619804457947208"); 359 360 // precalculation 361 string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; 362 string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; 363 string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; 364 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 365 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 366 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 367 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 368 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 369 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 370 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 371 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 372 CurveGFp secp160r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 373 PointGFp p_G = OS2ECP( sv_G_secp_comp, secp160r1 ); 374 375 PointGFp p0 = p_G.dup; 376 p_G *= BigInt(2); 377 PointGFp p1 = p_G.dup; 378 379 p1 -= p0; 380 auto bi1 = BigInt("425826231723888350446541592701409065913635568770"); 381 auto bi2 = BigInt("203520114162904107873991457957346892027982641970"); 382 PointGFp expected = PointGFp(secp160r1, bi1, bi2); 383 384 mixin( CHECK(` p1 == expected `) ); 385 return fails; 386 } 387 388 size_t testMultPoint() 389 { 390 size_t fails = 0; 391 392 //Setting up expected values 393 BigInt exp_mult_x = BigInt("967697346845926834906555988570157345422864716250"); 394 BigInt exp_mult_y = BigInt("512319768365374654866290830075237814703869061656"); 395 396 // precalculation 397 string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; 398 string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; 399 string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; 400 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 401 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 402 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 403 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 404 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 405 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 406 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 407 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 408 CurveGFp secp160r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 409 PointGFp p_G = OS2ECP( sv_G_secp_comp, secp160r1 ); 410 411 PointGFp p0 = p_G.dup; 412 p_G *= BigInt(2); 413 PointGFp p1 = p_G.dup; 414 415 p1 *= p0.getAffineX(); 416 417 PointGFp expected = PointGFp(secp160r1, exp_mult_x, exp_mult_y); 418 419 mixin( CHECK(` p1 == expected `) ); 420 return fails; 421 } 422 423 size_t testBasicOperations() 424 { 425 size_t fails = 0; 426 427 // precalculation 428 string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; 429 string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; 430 string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; 431 string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; 432 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 433 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 434 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 435 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 436 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 437 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 438 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 439 CurveGFp secp160r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 440 441 PointGFp p_G = OS2ECP( sv_G_secp_comp, secp160r1 ); 442 443 PointGFp p0 = p_G.dup; 444 445 BigInt bi1 = BigInt("425826231723888350446541592701409065913635568770"); 446 BigInt bi2 = BigInt("203520114162904107873991457957346892027982641970"); 447 PointGFp expected = PointGFp(secp160r1, bi1, bi2); 448 449 mixin( CHECK(` p0 == expected `) ); 450 p_G *= BigInt(2); 451 PointGFp p1 = p_G.dup; 452 453 mixin( CHECK(` p1.getAffineX() == BigInt("16984103820118642236896513183038186009872590470") `) ); 454 mixin( CHECK(` p1.getAffineY() == BigInt("1373093393927139016463695321221277758035357890939") `) ); 455 456 PointGFp simplePlus = p1 + p0; 457 458 bi1 = BigInt("704859595002530890444080436569091156047721708633"); 459 bi2 = BigInt("1147993098458695153857594941635310323215433166682"); 460 PointGFp exp_simplePlus = PointGFp(secp160r1, bi1, bi2); 461 if (simplePlus != exp_simplePlus) 462 logTrace(simplePlus.toString() ~ " != " ~ exp_simplePlus.toString()); 463 464 PointGFp simpleMinus= p1 - p0; 465 bi1 = BigInt("425826231723888350446541592701409065913635568770"); 466 bi2 = BigInt("203520114162904107873991457957346892027982641970"); 467 PointGFp exp_simpleMinus = PointGFp(secp160r1, bi1, bi2); 468 469 mixin( CHECK(` simpleMinus == exp_simpleMinus `) ); 470 471 PointGFp simpleMult= p1 * BigInt(123456789); 472 473 mixin( CHECK(` simpleMult.getAffineX() == BigInt("43638877777452195295055270548491599621118743290") `) ); 474 mixin( CHECK(` simpleMult.getAffineY() == BigInt("56841378500012376527163928510402662349220202981") `) ); 475 476 // check that all initial points hasn't changed 477 mixin( CHECK(` p1.getAffineX() == BigInt("16984103820118642236896513183038186009872590470") `) ); 478 mixin( CHECK(` p1.getAffineY() == BigInt("1373093393927139016463695321221277758035357890939") `) ); 479 480 mixin( CHECK(` p0.getAffineX() == BigInt("425826231723888350446541592701409065913635568770") `) ); 481 mixin( CHECK(` p0.getAffineY() == BigInt("203520114162904107873991457957346892027982641970") `) ); 482 return fails; 483 } 484 485 size_t testEncDecCompressed160() 486 { 487 size_t fails = 0; 488 489 // Test for compressed conversion (02/03) 160bit 490 string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; 491 string a_secp = "ffffffffffffffffffffffffffffffff7ffffffC"; 492 string b_secp = "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"; 493 string G_secp_comp = "024A96B5688EF573284664698968C38BB913CBFC82"; 494 string G_order_secp_comp = "0100000000000000000001F4C8F927AED3CA752257"; 495 496 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 497 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 498 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 499 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 500 501 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 502 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 503 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 504 505 CurveGFp secp160r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 506 507 PointGFp p_G = OS2ECP( sv_G_secp_comp, secp160r1 ); 508 Vector!ubyte sv_result = unlock(EC2OSP(p_G, PointGFp.COMPRESSED)); 509 510 mixin( CHECK(` sv_result == sv_G_secp_comp `) ); 511 return fails; 512 } 513 514 size_t testEncDecCompressed256() 515 { 516 size_t fails = 0; 517 518 // Test for compressed conversion (02/03) 256bit 519 string p_secp = "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"; 520 string a_secp = "ffffffff00000001000000000000000000000000ffffffffffffffffffffffFC"; 521 string b_secp = "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"; 522 string G_secp_comp = "036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; 523 string G_order_secp_comp = "ffffffff00000000ffffffffffffffffBCE6FAADA7179E84F3B9CAC2FC632551"; 524 525 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 526 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 527 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 528 Vector!ubyte sv_G_secp_comp = hexDecode( G_secp_comp ); 529 530 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 531 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 532 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 533 534 CurveGFp curve = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 535 536 PointGFp p_G = OS2ECP( sv_G_secp_comp, curve ); 537 Vector!ubyte sv_result = unlock(EC2OSP(p_G, PointGFp.COMPRESSED)); 538 539 mixin( CHECK(` sv_result == sv_G_secp_comp `) ); 540 return fails; 541 } 542 543 544 size_t testEncDecUncompressed112() 545 { 546 size_t fails = 0; 547 548 // Test for uncompressed conversion (04) 112bit 549 550 string p_secp = "db7c2abf62e35e668076bead208b"; 551 string a_secp = "6127C24C05F38A0AAAF65C0EF02C"; 552 string b_secp = "51DEF1815DB5ED74FCC34C85D709"; 553 string G_secp_uncomp = "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97"; 554 string G_order_secp_uncomp = "36DF0AAFD8B8D7597CA10520D04B"; 555 556 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 557 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 558 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 559 Vector!ubyte sv_G_secp_uncomp = hexDecode( G_secp_uncomp ); 560 561 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 562 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 563 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 564 565 CurveGFp curve = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 566 567 PointGFp p_G = OS2ECP( sv_G_secp_uncomp, curve ); 568 Vector!ubyte sv_result = unlock(EC2OSP(p_G, PointGFp.UNCOMPRESSED)); 569 570 mixin( CHECK(` sv_result == sv_G_secp_uncomp `) ); 571 return fails; 572 } 573 574 size_t testEncDecUncompressed521() 575 { 576 size_t fails = 0; 577 578 // Test for uncompressed conversion(04) with big values(521 bit) 579 string p_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; 580 string a_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFC"; 581 string b_secp = "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"; 582 string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"; 583 string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"; 584 585 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 586 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 587 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 588 Vector!ubyte sv_G_secp_uncomp = hexDecode( G_secp_uncomp ); 589 590 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 591 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 592 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 593 594 CurveGFp curve = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 595 596 PointGFp p_G = OS2ECP( sv_G_secp_uncomp, curve ); 597 598 Vector!ubyte sv_result = unlock(EC2OSP(p_G, PointGFp.UNCOMPRESSED)); 599 string result = hexEncode(sv_result.ptr, sv_result.length); 600 string exp_result = hexEncode(&sv_G_secp_uncomp[0], sv_G_secp_uncomp.length); 601 602 mixin( CHECK_MESSAGE( `sv_result == sv_G_secp_uncomp`, "\ncalc. result = ` ~ result ~ `\nexp. result = ` ~ exp_result ~ ` \n" ) ); 603 return fails; 604 } 605 606 size_t testEncDecUncompressed521PrimeTooLarge() 607 { 608 size_t fails = 0; 609 610 // Test for uncompressed conversion(04) with big values(521 bit) 611 string p_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // length increased by "ff" 612 string a_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFC"; 613 string b_secp = "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"; 614 string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"; 615 string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"; 616 617 Vector!ubyte sv_p_secp = hexDecode( p_secp ); 618 Vector!ubyte sv_a_secp = hexDecode( a_secp ); 619 Vector!ubyte sv_b_secp = hexDecode( b_secp ); 620 Vector!ubyte sv_G_secp_uncomp = hexDecode( G_secp_uncomp ); 621 622 BigInt bi_p_secp = BigInt.decode( sv_p_secp.ptr, sv_p_secp.length ); 623 BigInt bi_a_secp = BigInt.decode( sv_a_secp.ptr, sv_a_secp.length ); 624 BigInt bi_b_secp = BigInt.decode( sv_b_secp.ptr, sv_b_secp.length ); 625 626 CurveGFp secp521r1 = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 627 PointGFp p_G; 628 bool exc = false; 629 try 630 { 631 auto os2ecp = OS2ECP(sv_G_secp_uncomp, secp521r1); 632 p_G = os2ecp.move(); 633 if (!p_G.onTheCurve()) 634 throw new InternalError("Point not on the curve"); 635 } 636 catch (Exception e) 637 { 638 exc = true; 639 } 640 641 mixin( CHECK_MESSAGE( `exc`, "attempt of creation of point on curve with too high prime did not throw an exception" ) ); 642 return fails; 643 } 644 645 size_t testGfpStoreRestore() 646 { 647 size_t fails = 0; 648 649 // generate point 650 //ECGroup dom_pars = global_config().get_ec_dompar("1.3.132.0.8"); 651 //ECGroup dom_pars = ECGroup("1.3.132.0.8"); 652 ECGroup dom_pars = ECGroup(OID("1.3.132.0.8")); 653 PointGFp p = dom_pars.getBasePoint().dup; 654 655 //store point (to string) 656 Vector!ubyte sv_mes = unlock(EC2OSP(p, PointGFp.COMPRESSED)); 657 PointGFp new_p = OS2ECP(sv_mes, dom_pars.getCurve()); 658 659 mixin( CHECK_MESSAGE( `p == new_p`, "original and restored point are different!" ) ); 660 return fails; 661 } 662 663 664 // maybe move this test 665 size_t testCdcCurve33() 666 { 667 size_t fails = 0; 668 669 string G_secp_uncomp = "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7"; 670 671 Vector!ubyte sv_G_uncomp = hexDecode( G_secp_uncomp ); 672 673 BigInt bi_p_secp = BigInt("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809"); 674 BigInt bi_a_secp = BigInt("0xa377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe"); 675 BigInt bi_b_secp = BigInt("0xa9acf8c8ba617777e248509bcb4717d4db346202bf9e352cd5633731dd92a51b72a4dc3b3d17c823fcc8fbda4da08f25dea89046087342595a7"); 676 677 CurveGFp curve = CurveGFp(bi_p_secp, bi_a_secp, bi_b_secp); 678 PointGFp p_G = OS2ECP( sv_G_uncomp, curve); 679 bool exc = false; 680 try 681 { 682 if (!p_G.onTheCurve()) 683 throw new InternalError("Point not on the curve"); 684 } 685 catch (Exception) 686 { 687 exc = true; 688 } 689 mixin( CHECK(` !exc `) ); 690 return fails; 691 } 692 693 size_t testMoreZeropoint() 694 { 695 size_t fails = 0; 696 697 // by Falko 698 699 string G = "024a96b5688ef573284664698968c38bb913cbfc82"; 700 Vector!ubyte sv_G_secp_comp = hexDecode( G ); 701 BigInt bi_p = BigInt("0xffffffffffffffffffffffffffffffff7fffffff"); 702 BigInt bi_a = BigInt("0xffffffffffffffffffffffffffffffff7ffffffc"); 703 BigInt bi_b = BigInt("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); 704 CurveGFp curve = CurveGFp(bi_p, bi_a, bi_b); 705 706 auto bi1 = BigInt("16984103820118642236896513183038186009872590470"); 707 auto bi2 = BigInt("1373093393927139016463695321221277758035357890939"); 708 PointGFp p1 = PointGFp(curve, bi1, bi2); 709 710 if (!p1.onTheCurve()) 711 throw new InternalError("Point not on the curve"); 712 PointGFp minus_p1 = -p1; 713 if (!minus_p1.onTheCurve()) 714 throw new InternalError("Point not on the curve"); 715 PointGFp shouldBeZero = p1 + minus_p1; 716 if (!shouldBeZero.onTheCurve()) 717 throw new InternalError("Point not on the curve"); 718 719 BigInt y1 = p1.getAffineY(); 720 y1 = curve.getP() - y1; 721 722 CHECK_MESSAGE(`p1.getAffineX() == minus_p1.getAffineX()`, 723 "problem with minus_p1 : x"); 724 CHECK_MESSAGE(`minus_p1.getAffineY() == y1`, 725 "problem with minus_p1 : y"); 726 727 PointGFp zero = PointGFp(curve); 728 if (!zero.onTheCurve()) 729 throw new InternalError("Point not on the curve"); 730 mixin( CHECK_MESSAGE( `p1 + zero == p1`, "addition of zero modified point" ) ); 731 732 mixin( CHECK_MESSAGE( `shouldBeZero.isZero()`, "p - q with q = p is not zero!" ) ); 733 return fails; 734 } 735 736 size_t testMultByOrder() 737 { 738 size_t fails = 0; 739 740 // generate point 741 ECGroup dom_pars = ECGroup(OID("1.3.132.0.8")); 742 PointGFp p = dom_pars.getBasePoint().dup; 743 PointGFp shouldBeZero = p * dom_pars.getOrder(); 744 745 mixin( CHECK_MESSAGE( `shouldBeZero.isZero()`, "G * order != O" ) ); 746 return fails; 747 } 748 749 size_t testPointSwap() 750 { 751 size_t fails = 0; 752 753 ECGroup dom_pars = ECGroup(OID("1.3.132.0.8")); 754 755 Unique!AutoSeededRNG rng = new AutoSeededRNG; 756 757 PointGFp a = createRandomPoint(*rng, dom_pars.getCurve()); 758 PointGFp b = createRandomPoint(*rng, dom_pars.getCurve()); 759 b *= BigInt(20); 760 761 PointGFp c = a.dup; 762 PointGFp d = b.dup; 763 764 d.swap(c); 765 mixin( CHECK(` a == d `) ); 766 mixin( CHECK(` b == c `) ); 767 return fails; 768 } 769 770 /** 771 * This test verifies that the side channel attack resistant multiplication function 772 * yields the same result as the normal (insecure) multiplication via operator*= 773 */ 774 size_t testMultSecMass() 775 { 776 size_t fails = 0; 777 778 Unique!AutoSeededRNG rng = new AutoSeededRNG; 779 780 ECGroup dom_pars = ECGroup(OID("1.3.132.0.8")); 781 for(int i = 0; i<50; i++) 782 { 783 PointGFp a = createRandomPoint(*rng, dom_pars.getCurve()); 784 BigInt scal = BigInt(*rng, 40); 785 PointGFp b = a * scal; 786 PointGFp c = a.dup; 787 788 c *= scal; 789 mixin( CHECK(` b == c `) ); 790 } 791 return fails; 792 } 793 794 size_t testCurveCpCtor() 795 { 796 try 797 { 798 ECGroup dom_pars = ECGroup(OID("1.3.132.0.8")); 799 CurveGFp curve = dom_pars.getCurve().dup; 800 } 801 catch (Exception) 802 { 803 return 1; 804 805 } 806 807 return 0; 808 } 809 810 811 size_t randomizedTest(RandomNumberGenerator rng, const ref ECGroup group) 812 { 813 auto b2 = BigInt(2); 814 const BigInt a = BigInt.randomInteger(rng, b2, group.getOrder()); 815 const BigInt b = BigInt.randomInteger(rng, b2, group.getOrder()); 816 const BigInt c = a + b; 817 818 const PointGFp P = group.getBasePoint() * a; 819 const PointGFp Q = group.getBasePoint() * b; 820 const PointGFp R = group.getBasePoint() * c; 821 822 const PointGFp A1 = P + Q; 823 const PointGFp A2 = Q + P; 824 825 size_t fails = 0; 826 827 mixin( CHECK(`A1 == R`) ); 828 mixin( CHECK(`A2 == R`) ); 829 mixin( CHECK(`P.onTheCurve()`) ); 830 mixin( CHECK(`Q.onTheCurve()`) ); 831 mixin( CHECK(`R.onTheCurve()`) ); 832 mixin( CHECK(`A1.onTheCurve()`) ); 833 mixin( CHECK(`A2.onTheCurve()`) ); 834 835 return fails; 836 } 837 838 size_t randomizedTest() 839 { 840 Unique!AutoSeededRNG rng = new AutoSeededRNG; 841 size_t fails = 0; 842 843 const string[] groups = [ 844 "brainpool160r1", 845 "brainpool192r1", 846 "brainpool224r1", 847 "brainpool256r1", 848 "brainpool320r1", 849 "brainpool384r1", 850 "brainpool512r1", 851 "gost_256A", 852 "secp112r1", 853 "secp112r2", 854 "secp128r1", 855 "secp128r2", 856 "secp160k1", 857 "secp160r1", 858 "secp160r2", 859 "secp192k1", 860 "secp192r1", 861 "secp224k1", 862 "secp224r1", 863 "secp256k1", 864 "secp256r1", 865 "secp384r1", 866 "secp521r1", 867 "x962_p192v2", 868 "x962_p192v3", 869 "x962_p239v1", 870 "x962_p239v2", 871 "x962_p239v3" 872 ]; 873 874 foreach(group_name; groups) 875 { 876 ECGroup group = ECGroup(group_name); 877 878 PointGFp inf = group.getBasePoint() * group.getOrder(); 879 mixin( CHECK(`inf.isZero()`) ); 880 881 for(size_t i = 0; i != 32; ++i) 882 fails += randomizedTest(*rng, group); 883 } 884 885 return fails; 886 } 887 888 static if (BOTAN_HAS_TESTS && !SKIP_EC_GFP_TEST) unittest 889 { 890 import botan.libstate.global_state; 891 auto state = globalState(); // ensure initialized 892 893 logDebug("Testing ec_gfp/test.d ..."); 894 size_t fails = 0; 895 896 logTrace("testPointTurnOnSpRedMul"); 897 fails += testPointTurnOnSpRedMul(); 898 logTrace("testCoordinates"); 899 fails += testCoordinates(); 900 logTrace("testPointTransformation"); 901 fails += testPointTransformation (); 902 logTrace("testPointMult"); 903 fails += testPointMult (); 904 logTrace("testPointNegative"); 905 fails += testPointNegative(); 906 logTrace("testZeropoint"); 907 fails += testZeropoint(); 908 logTrace("testZeropointEncDec"); 909 fails += testZeropointEncDec(); 910 logTrace("testCalcWithZeropoint"); 911 fails += testCalcWithZeropoint(); 912 logTrace("testAddPoint"); 913 fails += testAddPoint(); 914 logTrace("testSubPoint"); 915 fails += testSubPoint(); 916 logTrace("testMultPoint"); 917 fails += testMultPoint(); 918 logTrace("testBasicOperations"); 919 fails += testBasicOperations(); 920 logTrace("testEncDecCompressed160"); 921 fails += testEncDecCompressed160(); 922 logTrace("testEncDecCompressed256"); 923 fails += testEncDecCompressed256(); 924 logTrace("testEncDecUncompressed112"); 925 fails += testEncDecUncompressed112(); 926 logTrace("testEncDecUncompressed521"); 927 fails += testEncDecUncompressed521(); 928 logTrace("testEncDecUncompressed521PrimeTooLarge"); 929 fails += testEncDecUncompressed521PrimeTooLarge(); 930 logTrace("testGfpStoreRestore"); 931 fails += testGfpStoreRestore(); 932 logTrace("testCdcCurve33"); 933 fails += testCdcCurve33(); 934 logTrace("testMoreZeropoint"); 935 fails += testMoreZeropoint(); 936 logTrace("testMultByOrder"); 937 fails += testMultByOrder(); 938 logTrace("testPointSwap"); 939 fails += testPointSwap(); 940 logTrace("testMultSecMass"); 941 fails += testMultSecMass(); 942 logTrace("testCurveCpCtor"); 943 fails += testCurveCpCtor(); 944 logTrace("randomizedTest"); 945 fails += randomizedTest(); 946 947 testReport("ECC", total_tests, fails); 948 949 }