1# This file is dual licensed under the terms of the Apache License, Version 2# 2.0, and the BSD License. See the LICENSE file in the root of this repository 3# for complete details. 4 5from __future__ import absolute_import, division, print_function 6 7import binascii 8import itertools 9import os 10from binascii import hexlify 11 12import pytest 13 14from cryptography import exceptions, utils, x509 15from cryptography.hazmat.backends.interfaces import ( 16 EllipticCurveBackend, 17 PEMSerializationBackend, 18) 19from cryptography.hazmat.primitives import hashes, serialization 20from cryptography.hazmat.primitives.asymmetric import ec 21from cryptography.hazmat.primitives.asymmetric.utils import ( 22 Prehashed, 23 encode_dss_signature, 24) 25from cryptography.utils import CryptographyDeprecationWarning 26 27from .fixtures_ec import EC_KEY_SECP384R1 28from .utils import skip_fips_traditional_openssl 29from ...doubles import DummyKeySerializationEncryption 30from ...utils import ( 31 load_fips_ecdsa_key_pair_vectors, 32 load_fips_ecdsa_signing_vectors, 33 load_kasvs_ecdh_vectors, 34 load_nist_vectors, 35 load_vectors_from_file, 36 raises_unsupported_algorithm, 37) 38 39_HASH_TYPES = { 40 "SHA-1": hashes.SHA1, 41 "SHA-224": hashes.SHA224, 42 "SHA-256": hashes.SHA256, 43 "SHA-384": hashes.SHA384, 44 "SHA-512": hashes.SHA512, 45} 46 47 48def _skip_ecdsa_vector(backend, curve_type, hash_type): 49 if not backend.elliptic_curve_signature_algorithm_supported( 50 ec.ECDSA(hash_type()), curve_type() 51 ): 52 pytest.skip( 53 "ECDSA not supported with this hash {} and curve {}.".format( 54 hash_type().name, curve_type().name 55 ) 56 ) 57 58 59def _skip_curve_unsupported(backend, curve): 60 if not backend.elliptic_curve_supported(curve): 61 pytest.skip( 62 "Curve {} is not supported by this backend {}".format( 63 curve.name, backend 64 ) 65 ) 66 67 68def _skip_exchange_algorithm_unsupported(backend, algorithm, curve): 69 if not backend.elliptic_curve_exchange_algorithm_supported( 70 algorithm, curve 71 ): 72 pytest.skip( 73 "Exchange with {} curve is not supported by {}".format( 74 curve.name, backend 75 ) 76 ) 77 78 79def test_get_curve_for_oid(): 80 assert ec.get_curve_for_oid(ec.EllipticCurveOID.SECP256R1) == ec.SECP256R1 81 with pytest.raises(LookupError): 82 ec.get_curve_for_oid(x509.ObjectIdentifier("1.1.1.1")) 83 84 85@utils.register_interface(ec.EllipticCurve) 86class DummyCurve(object): 87 name = "dummy-curve" 88 key_size = 1 89 90 91@utils.register_interface(ec.EllipticCurveSignatureAlgorithm) 92class DummySignatureAlgorithm(object): 93 algorithm = None 94 95 96@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 97def test_skip_curve_unsupported(backend): 98 with pytest.raises(pytest.skip.Exception): 99 _skip_curve_unsupported(backend, DummyCurve()) 100 101 102@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 103def test_skip_exchange_algorithm_unsupported(backend): 104 with pytest.raises(pytest.skip.Exception): 105 _skip_exchange_algorithm_unsupported(backend, ec.ECDH(), DummyCurve()) 106 107 108@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 109def test_skip_ecdsa_vector(backend): 110 with pytest.raises(pytest.skip.Exception): 111 _skip_ecdsa_vector(backend, DummyCurve, hashes.SHA256) 112 113 114@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 115def test_derive_private_key_success(backend): 116 curve = ec.SECP256K1() 117 _skip_curve_unsupported(backend, curve) 118 119 private_numbers = ec.generate_private_key(curve, backend).private_numbers() 120 121 derived_key = ec.derive_private_key( 122 private_numbers.private_value, curve, backend 123 ) 124 125 assert private_numbers == derived_key.private_numbers() 126 127 128@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 129def test_derive_private_key_errors(backend): 130 curve = ec.SECP256K1() 131 _skip_curve_unsupported(backend, curve) 132 133 with pytest.raises(TypeError): 134 ec.derive_private_key("one", curve, backend) 135 136 with pytest.raises(TypeError): 137 ec.derive_private_key(10, "five", backend) 138 139 with pytest.raises(ValueError): 140 ec.derive_private_key(-7, curve, backend) 141 142 143def test_ec_numbers(): 144 numbers = ec.EllipticCurvePrivateNumbers( 145 1, ec.EllipticCurvePublicNumbers(2, 3, DummyCurve()) 146 ) 147 148 assert numbers.private_value == 1 149 assert numbers.public_numbers.x == 2 150 assert numbers.public_numbers.y == 3 151 assert isinstance(numbers.public_numbers.curve, DummyCurve) 152 153 154@pytest.mark.parametrize( 155 ("private_value", "x", "y", "curve"), 156 [ 157 (None, 2, 3, DummyCurve()), 158 (1, None, 3, DummyCurve()), 159 (1, 2, None, DummyCurve()), 160 (1, 2, 3, None), 161 ], 162) 163def test_invalid_ec_numbers_args(private_value, x, y, curve): 164 with pytest.raises(TypeError): 165 ec.EllipticCurvePrivateNumbers( 166 private_value, ec.EllipticCurvePublicNumbers(x, y, curve) 167 ) 168 169 170def test_invalid_private_numbers_public_numbers(): 171 with pytest.raises(TypeError): 172 ec.EllipticCurvePrivateNumbers(1, None) 173 174 175def test_encode_point(): 176 # secp256r1 point 177 x = int( 178 "233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec", 16 179 ) 180 y = int( 181 "3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e", 16 182 ) 183 pn = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1()) 184 with pytest.warns(utils.PersistentlyDeprecated2019): 185 data = pn.encode_point() 186 assert data == binascii.unhexlify( 187 "04233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22ae" 188 "c3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e" 189 ) 190 191 192def test_from_encoded_point(): 193 # secp256r1 point 194 data = binascii.unhexlify( 195 "04233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22ae" 196 "c3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e" 197 ) 198 with pytest.warns(CryptographyDeprecationWarning): 199 pn = ec.EllipticCurvePublicNumbers.from_encoded_point( 200 ec.SECP256R1(), data 201 ) 202 assert pn.x == int( 203 "233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec", 16 204 ) 205 assert pn.y == int( 206 "3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e", 16 207 ) 208 209 210def test_from_encoded_point_invalid_length(): 211 bad_data = binascii.unhexlify( 212 "04233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22ae" 213 "c3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460" 214 ) 215 with pytest.raises(ValueError): 216 with pytest.warns(CryptographyDeprecationWarning): 217 ec.EllipticCurvePublicNumbers.from_encoded_point( 218 ec.SECP384R1(), bad_data 219 ) 220 221 222def test_from_encoded_point_unsupported_point_no_backend(): 223 # set to point type 2. 224 unsupported_type = binascii.unhexlify( 225 "02233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22a" 226 ) 227 with pytest.raises(ValueError): 228 with pytest.warns(CryptographyDeprecationWarning): 229 ec.EllipticCurvePublicNumbers.from_encoded_point( 230 ec.SECP256R1(), unsupported_type 231 ) 232 233 234def test_from_encoded_point_not_a_curve(): 235 with pytest.raises(TypeError): 236 with pytest.warns(CryptographyDeprecationWarning): 237 ec.EllipticCurvePublicNumbers.from_encoded_point( 238 "notacurve", b"\x04data" 239 ) 240 241 242def test_ec_public_numbers_repr(): 243 pn = ec.EllipticCurvePublicNumbers(2, 3, ec.SECP256R1()) 244 assert repr(pn) == "<EllipticCurvePublicNumbers(curve=secp256r1, x=2, y=3>" 245 246 247def test_ec_public_numbers_hash(): 248 pn1 = ec.EllipticCurvePublicNumbers(2, 3, ec.SECP256R1()) 249 pn2 = ec.EllipticCurvePublicNumbers(2, 3, ec.SECP256R1()) 250 pn3 = ec.EllipticCurvePublicNumbers(1, 3, ec.SECP256R1()) 251 252 assert hash(pn1) == hash(pn2) 253 assert hash(pn1) != hash(pn3) 254 255 256def test_ec_private_numbers_hash(): 257 numbers1 = ec.EllipticCurvePrivateNumbers( 258 1, ec.EllipticCurvePublicNumbers(2, 3, DummyCurve()) 259 ) 260 numbers2 = ec.EllipticCurvePrivateNumbers( 261 1, ec.EllipticCurvePublicNumbers(2, 3, DummyCurve()) 262 ) 263 numbers3 = ec.EllipticCurvePrivateNumbers( 264 2, ec.EllipticCurvePublicNumbers(2, 3, DummyCurve()) 265 ) 266 267 assert hash(numbers1) == hash(numbers2) 268 assert hash(numbers1) != hash(numbers3) 269 270 271@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 272def test_ec_key_key_size(backend): 273 curve = ec.SECP256R1() 274 _skip_curve_unsupported(backend, curve) 275 key = ec.generate_private_key(curve, backend) 276 assert key.key_size == 256 277 assert key.public_key().key_size == 256 278 279 280@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 281class TestECWithNumbers(object): 282 @pytest.mark.parametrize( 283 ("vector", "hash_type"), 284 list( 285 itertools.product( 286 load_vectors_from_file( 287 os.path.join( 288 "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp" 289 ), 290 load_fips_ecdsa_key_pair_vectors, 291 ), 292 _HASH_TYPES.values(), 293 ) 294 ), 295 ) 296 def test_with_numbers(self, backend, vector, hash_type): 297 curve_type = ec._CURVE_TYPES[vector["curve"]] 298 299 _skip_ecdsa_vector(backend, curve_type, hash_type) 300 301 key = ec.EllipticCurvePrivateNumbers( 302 vector["d"], 303 ec.EllipticCurvePublicNumbers( 304 vector["x"], vector["y"], curve_type() 305 ), 306 ).private_key(backend) 307 assert key 308 309 priv_num = key.private_numbers() 310 assert priv_num.private_value == vector["d"] 311 assert priv_num.public_numbers.x == vector["x"] 312 assert priv_num.public_numbers.y == vector["y"] 313 assert curve_type().name == priv_num.public_numbers.curve.name 314 315 316@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 317class TestECDSAVectors(object): 318 @pytest.mark.parametrize( 319 ("vector", "hash_type"), 320 list( 321 itertools.product( 322 load_vectors_from_file( 323 os.path.join( 324 "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp" 325 ), 326 load_fips_ecdsa_key_pair_vectors, 327 ), 328 _HASH_TYPES.values(), 329 ) 330 ), 331 ) 332 def test_signing_with_example_keys(self, backend, vector, hash_type): 333 curve_type = ec._CURVE_TYPES[vector["curve"]] 334 335 _skip_ecdsa_vector(backend, curve_type, hash_type) 336 337 key = ec.EllipticCurvePrivateNumbers( 338 vector["d"], 339 ec.EllipticCurvePublicNumbers( 340 vector["x"], vector["y"], curve_type() 341 ), 342 ).private_key(backend) 343 assert key 344 345 pkey = key.public_key() 346 assert pkey 347 348 with pytest.warns(CryptographyDeprecationWarning): 349 signer = key.signer(ec.ECDSA(hash_type())) 350 signer.update(b"YELLOW SUBMARINE") 351 signature = signer.finalize() 352 353 with pytest.warns(CryptographyDeprecationWarning): 354 verifier = pkey.verifier(signature, ec.ECDSA(hash_type())) 355 verifier.update(b"YELLOW SUBMARINE") 356 verifier.verify() 357 358 @pytest.mark.parametrize("curve", ec._CURVE_TYPES.values()) 359 def test_generate_vector_curves(self, backend, curve): 360 _skip_curve_unsupported(backend, curve()) 361 362 key = ec.generate_private_key(curve(), backend) 363 assert key 364 assert isinstance(key.curve, curve) 365 assert key.curve.key_size 366 367 pkey = key.public_key() 368 assert pkey 369 assert isinstance(pkey.curve, curve) 370 assert key.curve.key_size == pkey.curve.key_size 371 372 def test_generate_unknown_curve(self, backend): 373 with raises_unsupported_algorithm( 374 exceptions._Reasons.UNSUPPORTED_ELLIPTIC_CURVE 375 ): 376 ec.generate_private_key(DummyCurve(), backend) 377 378 assert ( 379 backend.elliptic_curve_signature_algorithm_supported( 380 ec.ECDSA(hashes.SHA256()), DummyCurve() 381 ) 382 is False 383 ) 384 385 def test_unknown_signature_algoritm(self, backend): 386 _skip_curve_unsupported(backend, ec.SECP192R1()) 387 388 key = ec.generate_private_key(ec.SECP192R1(), backend) 389 390 with raises_unsupported_algorithm( 391 exceptions._Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM 392 ), pytest.warns(CryptographyDeprecationWarning): 393 key.signer(DummySignatureAlgorithm()) 394 395 with raises_unsupported_algorithm( 396 exceptions._Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM 397 ): 398 key.sign(b"somedata", DummySignatureAlgorithm()) 399 400 with raises_unsupported_algorithm( 401 exceptions._Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM 402 ), pytest.warns(CryptographyDeprecationWarning): 403 key.public_key().verifier(b"", DummySignatureAlgorithm()) 404 405 with raises_unsupported_algorithm( 406 exceptions._Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM 407 ): 408 key.public_key().verify( 409 b"signature", b"data", DummySignatureAlgorithm() 410 ) 411 412 assert ( 413 backend.elliptic_curve_signature_algorithm_supported( 414 DummySignatureAlgorithm(), ec.SECP192R1() 415 ) 416 is False 417 ) 418 419 def test_load_invalid_ec_key_from_numbers(self, backend): 420 _skip_curve_unsupported(backend, ec.SECP256R1()) 421 422 numbers = ec.EllipticCurvePrivateNumbers( 423 357646505660320080863666618182642070958081774038609089496899025506, 424 ec.EllipticCurvePublicNumbers( 425 47250808410327023131573602008345894927686381772325561185532964, 426 1120253292479243545483756778742719537373113335231773536789915, 427 ec.SECP256R1(), 428 ), 429 ) 430 with pytest.raises(ValueError): 431 numbers.private_key(backend) 432 433 numbers = ec.EllipticCurvePrivateNumbers( 434 357646505660320080863666618182642070958081774038609089496899025506, 435 ec.EllipticCurvePublicNumbers( 436 -4725080841032702313157360200834589492768638177232556118553296, 437 1120253292479243545483756778742719537373113335231773536789915, 438 ec.SECP256R1(), 439 ), 440 ) 441 with pytest.raises(ValueError): 442 numbers.private_key(backend) 443 444 numbers = ec.EllipticCurvePrivateNumbers( 445 357646505660320080863666618182642070958081774038609089496899025506, 446 ec.EllipticCurvePublicNumbers( 447 47250808410327023131573602008345894927686381772325561185532964, 448 -1120253292479243545483756778742719537373113335231773536789915, 449 ec.SECP256R1(), 450 ), 451 ) 452 with pytest.raises(ValueError): 453 numbers.private_key(backend) 454 455 def test_load_invalid_public_ec_key_from_numbers(self, backend): 456 _skip_curve_unsupported(backend, ec.SECP521R1()) 457 458 # Bad X coordinate 459 numbers = ec.EllipticCurvePublicNumbers( 460 int( 461 "000003647356b91f8ace114c7247ecf4f4a622553fc025e04a178f179ef27" 462 "9090c184af678a4c78f635483bdd8aa544851c6ef291c1f0d6a241ebfd145" 463 "77d1d30d9903ce", 464 16, 465 ), 466 int( 467 "000001499bc7e079322ea0fcfbd6b40103fa6a1536c2257b182db0df4b369" 468 "6ec643adf100eb4f2025d1b873f82e5a475d6e4400ba777090eeb4563a115" 469 "09e4c87319dc26", 470 16, 471 ), 472 ec.SECP521R1(), 473 ) 474 with pytest.raises(ValueError): 475 numbers.public_key(backend) 476 477 # Bad Y coordinate 478 numbers = ec.EllipticCurvePublicNumbers( 479 int( 480 "0000019aadc221cc0525118ab6d5aa1f64720603de0be128cbfea0b381ad8" 481 "02a2facc6370bb58cf88b3f0c692bc654ee19d6cad198f10d4b681b396f20" 482 "d2e40603fa945b", 483 16, 484 ), 485 int( 486 "0000025da392803a320717a08d4cb3dea932039badff363b71bdb8064e726" 487 "6c7f4f4b748d4d425347fc33e3885d34b750fa7fcd5691f4d90c89522ce33" 488 "feff5db10088a5", 489 16, 490 ), 491 ec.SECP521R1(), 492 ) 493 with pytest.raises(ValueError): 494 numbers.public_key(backend) 495 496 @pytest.mark.parametrize( 497 "vector", 498 itertools.chain( 499 load_vectors_from_file( 500 os.path.join( 501 "asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt" 502 ), 503 load_fips_ecdsa_signing_vectors, 504 ), 505 load_vectors_from_file( 506 os.path.join("asymmetric", "ECDSA", "SECP256K1", "SigGen.txt"), 507 load_fips_ecdsa_signing_vectors, 508 ), 509 ), 510 ) 511 def test_signatures(self, backend, vector): 512 hash_type = _HASH_TYPES[vector["digest_algorithm"]] 513 curve_type = ec._CURVE_TYPES[vector["curve"]] 514 515 _skip_ecdsa_vector(backend, curve_type, hash_type) 516 517 key = ec.EllipticCurvePublicNumbers( 518 vector["x"], vector["y"], curve_type() 519 ).public_key(backend) 520 521 signature = encode_dss_signature(vector["r"], vector["s"]) 522 523 key.verify(signature, vector["message"], ec.ECDSA(hash_type())) 524 525 @pytest.mark.parametrize( 526 "vector", 527 load_vectors_from_file( 528 os.path.join("asymmetric", "ECDSA", "FIPS_186-3", "SigVer.rsp"), 529 load_fips_ecdsa_signing_vectors, 530 ), 531 ) 532 def test_signature_failures(self, backend, vector): 533 hash_type = _HASH_TYPES[vector["digest_algorithm"]] 534 curve_type = ec._CURVE_TYPES[vector["curve"]] 535 536 _skip_ecdsa_vector(backend, curve_type, hash_type) 537 538 key = ec.EllipticCurvePublicNumbers( 539 vector["x"], vector["y"], curve_type() 540 ).public_key(backend) 541 542 signature = encode_dss_signature(vector["r"], vector["s"]) 543 544 if vector["fail"] is True: 545 with pytest.raises(exceptions.InvalidSignature): 546 key.verify(signature, vector["message"], ec.ECDSA(hash_type())) 547 else: 548 key.verify(signature, vector["message"], ec.ECDSA(hash_type())) 549 550 def test_sign(self, backend): 551 _skip_curve_unsupported(backend, ec.SECP256R1()) 552 message = b"one little message" 553 algorithm = ec.ECDSA(hashes.SHA1()) 554 private_key = ec.generate_private_key(ec.SECP256R1(), backend) 555 signature = private_key.sign(message, algorithm) 556 public_key = private_key.public_key() 557 public_key.verify(signature, message, algorithm) 558 559 def test_sign_prehashed(self, backend): 560 _skip_curve_unsupported(backend, ec.SECP256R1()) 561 message = b"one little message" 562 h = hashes.Hash(hashes.SHA1(), backend) 563 h.update(message) 564 data = h.finalize() 565 algorithm = ec.ECDSA(Prehashed(hashes.SHA1())) 566 private_key = ec.generate_private_key(ec.SECP256R1(), backend) 567 signature = private_key.sign(data, algorithm) 568 public_key = private_key.public_key() 569 public_key.verify(signature, message, ec.ECDSA(hashes.SHA1())) 570 571 def test_sign_prehashed_digest_mismatch(self, backend): 572 _skip_curve_unsupported(backend, ec.SECP256R1()) 573 message = b"one little message" 574 h = hashes.Hash(hashes.SHA1(), backend) 575 h.update(message) 576 data = h.finalize() 577 algorithm = ec.ECDSA(Prehashed(hashes.SHA256())) 578 private_key = ec.generate_private_key(ec.SECP256R1(), backend) 579 with pytest.raises(ValueError): 580 private_key.sign(data, algorithm) 581 582 def test_verify(self, backend): 583 _skip_curve_unsupported(backend, ec.SECP256R1()) 584 message = b"one little message" 585 algorithm = ec.ECDSA(hashes.SHA1()) 586 private_key = ec.generate_private_key(ec.SECP256R1(), backend) 587 signature = private_key.sign(message, algorithm) 588 public_key = private_key.public_key() 589 public_key.verify(signature, message, algorithm) 590 591 def test_verify_prehashed(self, backend): 592 _skip_curve_unsupported(backend, ec.SECP256R1()) 593 message = b"one little message" 594 algorithm = ec.ECDSA(hashes.SHA1()) 595 private_key = ec.generate_private_key(ec.SECP256R1(), backend) 596 signature = private_key.sign(message, algorithm) 597 h = hashes.Hash(hashes.SHA1(), backend) 598 h.update(message) 599 data = h.finalize() 600 public_key = private_key.public_key() 601 public_key.verify(signature, data, ec.ECDSA(Prehashed(hashes.SHA1()))) 602 603 def test_verify_prehashed_digest_mismatch(self, backend): 604 _skip_curve_unsupported(backend, ec.SECP256R1()) 605 message = b"one little message" 606 private_key = ec.generate_private_key(ec.SECP256R1(), backend) 607 h = hashes.Hash(hashes.SHA1(), backend) 608 h.update(message) 609 data = h.finalize() 610 public_key = private_key.public_key() 611 with pytest.raises(ValueError): 612 public_key.verify( 613 b"\x00" * 32, data, ec.ECDSA(Prehashed(hashes.SHA256())) 614 ) 615 616 def test_prehashed_unsupported_in_signer_ctx(self, backend): 617 _skip_curve_unsupported(backend, ec.SECP256R1()) 618 private_key = ec.generate_private_key(ec.SECP256R1(), backend) 619 with pytest.raises(TypeError), pytest.warns( 620 CryptographyDeprecationWarning 621 ): 622 private_key.signer(ec.ECDSA(Prehashed(hashes.SHA1()))) 623 624 def test_prehashed_unsupported_in_verifier_ctx(self, backend): 625 _skip_curve_unsupported(backend, ec.SECP256R1()) 626 private_key = ec.generate_private_key(ec.SECP256R1(), backend) 627 public_key = private_key.public_key() 628 with pytest.raises(TypeError), pytest.warns( 629 CryptographyDeprecationWarning 630 ): 631 public_key.verifier(b"0" * 64, ec.ECDSA(Prehashed(hashes.SHA1()))) 632 633 634class TestECNumbersEquality(object): 635 def test_public_numbers_eq(self): 636 pub = ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1()) 637 assert pub == ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1()) 638 639 def test_public_numbers_ne(self): 640 pub = ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1()) 641 assert pub != ec.EllipticCurvePublicNumbers(1, 2, ec.SECP384R1()) 642 assert pub != ec.EllipticCurvePublicNumbers(1, 3, ec.SECP192R1()) 643 assert pub != ec.EllipticCurvePublicNumbers(2, 2, ec.SECP192R1()) 644 assert pub != object() 645 646 def test_private_numbers_eq(self): 647 pub = ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1()) 648 priv = ec.EllipticCurvePrivateNumbers(1, pub) 649 assert priv == ec.EllipticCurvePrivateNumbers( 650 1, ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1()) 651 ) 652 653 def test_private_numbers_ne(self): 654 pub = ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1()) 655 priv = ec.EllipticCurvePrivateNumbers(1, pub) 656 assert priv != ec.EllipticCurvePrivateNumbers( 657 2, ec.EllipticCurvePublicNumbers(1, 2, ec.SECP192R1()) 658 ) 659 assert priv != ec.EllipticCurvePrivateNumbers( 660 1, ec.EllipticCurvePublicNumbers(2, 2, ec.SECP192R1()) 661 ) 662 assert priv != ec.EllipticCurvePrivateNumbers( 663 1, ec.EllipticCurvePublicNumbers(1, 3, ec.SECP192R1()) 664 ) 665 assert priv != ec.EllipticCurvePrivateNumbers( 666 1, ec.EllipticCurvePublicNumbers(1, 2, ec.SECP521R1()) 667 ) 668 assert priv != object() 669 670 671@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 672@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) 673class TestECSerialization(object): 674 @pytest.mark.parametrize( 675 ("fmt", "password"), 676 itertools.product( 677 [ 678 serialization.PrivateFormat.TraditionalOpenSSL, 679 serialization.PrivateFormat.PKCS8, 680 ], 681 [ 682 b"s", 683 b"longerpassword", 684 b"!*$&(@#$*&($T@%_somesymbols", 685 b"\x01" * 1000, 686 ], 687 ), 688 ) 689 def test_private_bytes_encrypted_pem(self, backend, fmt, password): 690 skip_fips_traditional_openssl(backend, fmt) 691 _skip_curve_unsupported(backend, ec.SECP256R1()) 692 key_bytes = load_vectors_from_file( 693 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 694 lambda pemfile: pemfile.read().encode(), 695 ) 696 key = serialization.load_pem_private_key(key_bytes, None, backend) 697 serialized = key.private_bytes( 698 serialization.Encoding.PEM, 699 fmt, 700 serialization.BestAvailableEncryption(password), 701 ) 702 loaded_key = serialization.load_pem_private_key( 703 serialized, password, backend 704 ) 705 loaded_priv_num = loaded_key.private_numbers() 706 priv_num = key.private_numbers() 707 assert loaded_priv_num == priv_num 708 709 @pytest.mark.parametrize( 710 ("encoding", "fmt"), 711 [ 712 (serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8), 713 (serialization.Encoding.DER, serialization.PrivateFormat.Raw), 714 (serialization.Encoding.Raw, serialization.PrivateFormat.Raw), 715 (serialization.Encoding.X962, serialization.PrivateFormat.PKCS8), 716 ], 717 ) 718 def test_private_bytes_rejects_invalid(self, encoding, fmt, backend): 719 _skip_curve_unsupported(backend, ec.SECP256R1()) 720 key = ec.generate_private_key(ec.SECP256R1(), backend) 721 with pytest.raises(ValueError): 722 key.private_bytes(encoding, fmt, serialization.NoEncryption()) 723 724 @pytest.mark.parametrize( 725 ("fmt", "password"), 726 [ 727 [serialization.PrivateFormat.PKCS8, b"s"], 728 [serialization.PrivateFormat.PKCS8, b"longerpassword"], 729 [serialization.PrivateFormat.PKCS8, b"!*$&(@#$*&($T@%_somesymbol"], 730 [serialization.PrivateFormat.PKCS8, b"\x01" * 1000], 731 ], 732 ) 733 def test_private_bytes_encrypted_der(self, backend, fmt, password): 734 _skip_curve_unsupported(backend, ec.SECP256R1()) 735 key_bytes = load_vectors_from_file( 736 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 737 lambda pemfile: pemfile.read().encode(), 738 ) 739 key = serialization.load_pem_private_key(key_bytes, None, backend) 740 serialized = key.private_bytes( 741 serialization.Encoding.DER, 742 fmt, 743 serialization.BestAvailableEncryption(password), 744 ) 745 loaded_key = serialization.load_der_private_key( 746 serialized, password, backend 747 ) 748 loaded_priv_num = loaded_key.private_numbers() 749 priv_num = key.private_numbers() 750 assert loaded_priv_num == priv_num 751 752 @pytest.mark.parametrize( 753 ("encoding", "fmt", "loader_func"), 754 [ 755 [ 756 serialization.Encoding.PEM, 757 serialization.PrivateFormat.TraditionalOpenSSL, 758 serialization.load_pem_private_key, 759 ], 760 [ 761 serialization.Encoding.DER, 762 serialization.PrivateFormat.TraditionalOpenSSL, 763 serialization.load_der_private_key, 764 ], 765 [ 766 serialization.Encoding.PEM, 767 serialization.PrivateFormat.PKCS8, 768 serialization.load_pem_private_key, 769 ], 770 [ 771 serialization.Encoding.DER, 772 serialization.PrivateFormat.PKCS8, 773 serialization.load_der_private_key, 774 ], 775 ], 776 ) 777 def test_private_bytes_unencrypted( 778 self, backend, encoding, fmt, loader_func 779 ): 780 _skip_curve_unsupported(backend, ec.SECP256R1()) 781 key_bytes = load_vectors_from_file( 782 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 783 lambda pemfile: pemfile.read().encode(), 784 ) 785 key = serialization.load_pem_private_key(key_bytes, None, backend) 786 serialized = key.private_bytes( 787 encoding, fmt, serialization.NoEncryption() 788 ) 789 loaded_key = loader_func(serialized, None, backend) 790 loaded_priv_num = loaded_key.private_numbers() 791 priv_num = key.private_numbers() 792 assert loaded_priv_num == priv_num 793 794 @pytest.mark.skip_fips( 795 reason="Traditional OpenSSL key format is not supported in FIPS mode." 796 ) 797 @pytest.mark.parametrize( 798 ("key_path", "encoding", "loader_func"), 799 [ 800 [ 801 os.path.join( 802 "asymmetric", "PEM_Serialization", "ec_private_key.pem" 803 ), 804 serialization.Encoding.PEM, 805 serialization.load_pem_private_key, 806 ], 807 [ 808 os.path.join( 809 "asymmetric", "DER_Serialization", "ec_private_key.der" 810 ), 811 serialization.Encoding.DER, 812 serialization.load_der_private_key, 813 ], 814 ], 815 ) 816 def test_private_bytes_traditional_openssl_unencrypted( 817 self, backend, key_path, encoding, loader_func 818 ): 819 _skip_curve_unsupported(backend, ec.SECP256R1()) 820 key_bytes = load_vectors_from_file( 821 key_path, lambda pemfile: pemfile.read(), mode="rb" 822 ) 823 key = loader_func(key_bytes, None, backend) 824 serialized = key.private_bytes( 825 encoding, 826 serialization.PrivateFormat.TraditionalOpenSSL, 827 serialization.NoEncryption(), 828 ) 829 assert serialized == key_bytes 830 831 def test_private_bytes_traditional_der_encrypted_invalid(self, backend): 832 _skip_curve_unsupported(backend, ec.SECP256R1()) 833 key = load_vectors_from_file( 834 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 835 lambda pemfile: serialization.load_pem_private_key( 836 pemfile.read().encode(), None, backend 837 ), 838 ) 839 with pytest.raises(ValueError): 840 key.private_bytes( 841 serialization.Encoding.DER, 842 serialization.PrivateFormat.TraditionalOpenSSL, 843 serialization.BestAvailableEncryption(b"password"), 844 ) 845 846 def test_private_bytes_invalid_encoding(self, backend): 847 _skip_curve_unsupported(backend, ec.SECP256R1()) 848 key = load_vectors_from_file( 849 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 850 lambda pemfile: serialization.load_pem_private_key( 851 pemfile.read().encode(), None, backend 852 ), 853 ) 854 with pytest.raises(TypeError): 855 key.private_bytes( 856 "notencoding", 857 serialization.PrivateFormat.PKCS8, 858 serialization.NoEncryption(), 859 ) 860 861 def test_private_bytes_invalid_format(self, backend): 862 _skip_curve_unsupported(backend, ec.SECP256R1()) 863 key = load_vectors_from_file( 864 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 865 lambda pemfile: serialization.load_pem_private_key( 866 pemfile.read().encode(), None, backend 867 ), 868 ) 869 with pytest.raises(TypeError): 870 key.private_bytes( 871 serialization.Encoding.PEM, 872 "invalidformat", 873 serialization.NoEncryption(), 874 ) 875 876 def test_private_bytes_invalid_encryption_algorithm(self, backend): 877 _skip_curve_unsupported(backend, ec.SECP256R1()) 878 key = load_vectors_from_file( 879 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 880 lambda pemfile: serialization.load_pem_private_key( 881 pemfile.read().encode(), None, backend 882 ), 883 ) 884 with pytest.raises(TypeError): 885 key.private_bytes( 886 serialization.Encoding.PEM, 887 serialization.PrivateFormat.TraditionalOpenSSL, 888 "notanencalg", 889 ) 890 891 def test_private_bytes_unsupported_encryption_type(self, backend): 892 _skip_curve_unsupported(backend, ec.SECP256R1()) 893 key = load_vectors_from_file( 894 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 895 lambda pemfile: serialization.load_pem_private_key( 896 pemfile.read().encode(), None, backend 897 ), 898 ) 899 with pytest.raises(ValueError): 900 key.private_bytes( 901 serialization.Encoding.PEM, 902 serialization.PrivateFormat.TraditionalOpenSSL, 903 DummyKeySerializationEncryption(), 904 ) 905 906 def test_public_bytes_from_derived_public_key(self, backend): 907 _skip_curve_unsupported(backend, ec.SECP256R1()) 908 key = load_vectors_from_file( 909 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 910 lambda pemfile: serialization.load_pem_private_key( 911 pemfile.read().encode(), None, backend 912 ), 913 ) 914 public = key.public_key() 915 pem = public.public_bytes( 916 serialization.Encoding.PEM, 917 serialization.PublicFormat.SubjectPublicKeyInfo, 918 ) 919 parsed_public = serialization.load_pem_public_key(pem, backend) 920 assert parsed_public 921 922 923@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 924@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) 925class TestEllipticCurvePEMPublicKeySerialization(object): 926 @pytest.mark.parametrize( 927 ("key_path", "loader_func", "encoding"), 928 [ 929 ( 930 os.path.join( 931 "asymmetric", "PEM_Serialization", "ec_public_key.pem" 932 ), 933 serialization.load_pem_public_key, 934 serialization.Encoding.PEM, 935 ), 936 ( 937 os.path.join( 938 "asymmetric", "DER_Serialization", "ec_public_key.der" 939 ), 940 serialization.load_der_public_key, 941 serialization.Encoding.DER, 942 ), 943 ], 944 ) 945 def test_public_bytes_match( 946 self, key_path, loader_func, encoding, backend 947 ): 948 _skip_curve_unsupported(backend, ec.SECP256R1()) 949 key_bytes = load_vectors_from_file( 950 key_path, lambda pemfile: pemfile.read(), mode="rb" 951 ) 952 key = loader_func(key_bytes, backend) 953 serialized = key.public_bytes( 954 encoding, 955 serialization.PublicFormat.SubjectPublicKeyInfo, 956 ) 957 assert serialized == key_bytes 958 959 def test_public_bytes_openssh(self, backend): 960 _skip_curve_unsupported(backend, ec.SECP192R1()) 961 _skip_curve_unsupported(backend, ec.SECP256R1()) 962 963 key_bytes = load_vectors_from_file( 964 os.path.join( 965 "asymmetric", "PEM_Serialization", "ec_public_key.pem" 966 ), 967 lambda pemfile: pemfile.read(), 968 mode="rb", 969 ) 970 key = serialization.load_pem_public_key(key_bytes, backend) 971 972 ssh_bytes = key.public_bytes( 973 serialization.Encoding.OpenSSH, serialization.PublicFormat.OpenSSH 974 ) 975 assert ssh_bytes == ( 976 b"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAy" 977 b"NTYAAABBBCS8827s9rUZyxZTi/um01+oIlWrwLHOjQxRU9CDAndom00zVAw5BRrI" 978 b"KtHB+SWD4P+sVJTARSq1mHt8kOIWrPc=" 979 ) 980 981 key = ec.generate_private_key(ec.SECP192R1(), backend).public_key() 982 with pytest.raises(ValueError): 983 key.public_bytes( 984 serialization.Encoding.OpenSSH, 985 serialization.PublicFormat.OpenSSH, 986 ) 987 988 def test_public_bytes_invalid_encoding(self, backend): 989 _skip_curve_unsupported(backend, ec.SECP256R1()) 990 key = load_vectors_from_file( 991 os.path.join( 992 "asymmetric", "PEM_Serialization", "ec_public_key.pem" 993 ), 994 lambda pemfile: serialization.load_pem_public_key( 995 pemfile.read().encode(), backend 996 ), 997 ) 998 with pytest.raises(TypeError): 999 key.public_bytes( 1000 "notencoding", serialization.PublicFormat.SubjectPublicKeyInfo 1001 ) 1002 1003 @pytest.mark.parametrize( 1004 ("encoding", "fmt"), 1005 list( 1006 itertools.product( 1007 [ 1008 serialization.Encoding.Raw, 1009 serialization.Encoding.X962, 1010 serialization.Encoding.PEM, 1011 serialization.Encoding.DER, 1012 ], 1013 [serialization.PublicFormat.Raw], 1014 ) 1015 ) 1016 + list( 1017 itertools.product( 1018 [serialization.Encoding.Raw], 1019 [ 1020 serialization.PublicFormat.SubjectPublicKeyInfo, 1021 serialization.PublicFormat.PKCS1, 1022 serialization.PublicFormat.UncompressedPoint, 1023 serialization.PublicFormat.CompressedPoint, 1024 ], 1025 ) 1026 ), 1027 ) 1028 def test_public_bytes_rejects_invalid(self, encoding, fmt, backend): 1029 _skip_curve_unsupported(backend, ec.SECP256R1()) 1030 key = ec.generate_private_key(ec.SECP256R1(), backend).public_key() 1031 with pytest.raises(ValueError): 1032 key.public_bytes(encoding, fmt) 1033 1034 def test_public_bytes_invalid_format(self, backend): 1035 _skip_curve_unsupported(backend, ec.SECP256R1()) 1036 key = load_vectors_from_file( 1037 os.path.join( 1038 "asymmetric", "PEM_Serialization", "ec_public_key.pem" 1039 ), 1040 lambda pemfile: serialization.load_pem_public_key( 1041 pemfile.read().encode(), backend 1042 ), 1043 ) 1044 with pytest.raises(TypeError): 1045 key.public_bytes(serialization.Encoding.PEM, "invalidformat") 1046 1047 def test_public_bytes_pkcs1_unsupported(self, backend): 1048 _skip_curve_unsupported(backend, ec.SECP256R1()) 1049 key = load_vectors_from_file( 1050 os.path.join( 1051 "asymmetric", "PEM_Serialization", "ec_public_key.pem" 1052 ), 1053 lambda pemfile: serialization.load_pem_public_key( 1054 pemfile.read().encode(), backend 1055 ), 1056 ) 1057 with pytest.raises(ValueError): 1058 key.public_bytes( 1059 serialization.Encoding.PEM, serialization.PublicFormat.PKCS1 1060 ) 1061 1062 @pytest.mark.parametrize( 1063 "vector", 1064 load_vectors_from_file( 1065 os.path.join("asymmetric", "EC", "compressed_points.txt"), 1066 load_nist_vectors, 1067 ), 1068 ) 1069 def test_from_encoded_point_compressed(self, vector, backend): 1070 curve = {b"SECP256R1": ec.SECP256R1(), b"SECP256K1": ec.SECP256K1()}[ 1071 vector["curve"] 1072 ] 1073 _skip_curve_unsupported(backend, curve) 1074 point = binascii.unhexlify(vector["point"]) 1075 pn = ec.EllipticCurvePublicKey.from_encoded_point(curve, point) 1076 public_num = pn.public_numbers() 1077 assert public_num.x == int(vector["x"], 16) 1078 assert public_num.y == int(vector["y"], 16) 1079 1080 def test_from_encoded_point_notoncurve(self): 1081 uncompressed_point = binascii.unhexlify( 1082 "047399336a9edf2197c2f8eb3d39aed9c34a66e45d918a07dc7684c42c9b37ac" 1083 "686699ececc4f5f0d756d3c450708a0694eb0a07a68b805070b40b058d27271f" 1084 "6e" 1085 ) 1086 with pytest.raises(ValueError): 1087 ec.EllipticCurvePublicKey.from_encoded_point( 1088 ec.SECP256R1(), uncompressed_point 1089 ) 1090 1091 def test_from_encoded_point_uncompressed(self): 1092 uncompressed_point = binascii.unhexlify( 1093 "047399336a9edf2197c2f8eb3d39aed9c34a66e45d918a07dc7684c42c9b37ac" 1094 "686699ececc4f5f0d756d3c450708a0694eb0a07a68b805070b40b058d27271f" 1095 "6d" 1096 ) 1097 pn = ec.EllipticCurvePublicKey.from_encoded_point( 1098 ec.SECP256R1(), uncompressed_point 1099 ) 1100 assert pn.public_numbers().x == int( 1101 "7399336a9edf2197c2f8eb3d39aed9c34a66e45d918a07dc7684c42c9b37ac68", 1102 16, 1103 ) 1104 assert pn.public_numbers().y == int( 1105 "6699ececc4f5f0d756d3c450708a0694eb0a07a68b805070b40b058d27271f6d", 1106 16, 1107 ) 1108 1109 def test_from_encoded_point_invalid_length(self): 1110 bad_data = binascii.unhexlify( 1111 "047399336a9edf2197c2f8eb3d39aed9c34a66e45d918a07dc7684c42c9b37ac" 1112 "686699ececc4f5f0d756d3c450708a0694eb0a07a68b805070b40b058d27271f" 1113 "6d" 1114 ) 1115 with pytest.raises(ValueError): 1116 ec.EllipticCurvePublicKey.from_encoded_point( 1117 ec.SECP384R1(), bad_data 1118 ) 1119 1120 def test_from_encoded_point_empty_byte_string(self): 1121 with pytest.raises(ValueError): 1122 ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP384R1(), b"") 1123 1124 def test_from_encoded_point_not_a_curve(self): 1125 with pytest.raises(TypeError): 1126 ec.EllipticCurvePublicKey.from_encoded_point( 1127 "notacurve", b"\x04data" 1128 ) 1129 1130 def test_from_encoded_point_unsupported_encoding(self): 1131 unsupported_type = binascii.unhexlify( 1132 "057399336a9edf2197c2f8eb3d39aed9c34a66e45d918a07dc7684c42c9b37ac6" 1133 "8" 1134 ) 1135 with pytest.raises(ValueError): 1136 ec.EllipticCurvePublicKey.from_encoded_point( 1137 ec.SECP256R1(), unsupported_type 1138 ) 1139 1140 @pytest.mark.parametrize( 1141 "vector", 1142 load_vectors_from_file( 1143 os.path.join("asymmetric", "EC", "compressed_points.txt"), 1144 load_nist_vectors, 1145 ), 1146 ) 1147 def test_serialize_point(self, vector, backend): 1148 curve = {b"SECP256R1": ec.SECP256R1(), b"SECP256K1": ec.SECP256K1()}[ 1149 vector["curve"] 1150 ] 1151 _skip_curve_unsupported(backend, curve) 1152 point = binascii.unhexlify(vector["point"]) 1153 key = ec.EllipticCurvePublicKey.from_encoded_point(curve, point) 1154 key2 = ec.EllipticCurvePublicKey.from_encoded_point( 1155 curve, 1156 key.public_bytes( 1157 serialization.Encoding.X962, 1158 serialization.PublicFormat.UncompressedPoint, 1159 ), 1160 ) 1161 assert ( 1162 key.public_bytes( 1163 serialization.Encoding.X962, 1164 serialization.PublicFormat.CompressedPoint, 1165 ) 1166 == point 1167 ) 1168 assert ( 1169 key2.public_bytes( 1170 serialization.Encoding.X962, 1171 serialization.PublicFormat.CompressedPoint, 1172 ) 1173 == point 1174 ) 1175 1176 1177@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 1178class TestECDSAVerification(object): 1179 def test_signature_not_bytes(self, backend): 1180 _skip_curve_unsupported(backend, ec.SECP256R1()) 1181 key = ec.generate_private_key(ec.SECP256R1(), backend) 1182 public_key = key.public_key() 1183 with pytest.raises(TypeError), pytest.warns( 1184 CryptographyDeprecationWarning 1185 ): 1186 public_key.verifier(1234, ec.ECDSA(hashes.SHA256())) 1187 1188 1189@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) 1190class TestECDH(object): 1191 @pytest.mark.parametrize( 1192 "vector", 1193 load_vectors_from_file( 1194 os.path.join( 1195 "asymmetric", 1196 "ECDH", 1197 "KASValidityTest_ECCStaticUnified_NOKC_ZZOnly_init.fax", 1198 ), 1199 load_kasvs_ecdh_vectors, 1200 ), 1201 ) 1202 def test_key_exchange_with_vectors(self, backend, vector): 1203 _skip_exchange_algorithm_unsupported( 1204 backend, ec.ECDH(), ec._CURVE_TYPES[vector["curve"]] 1205 ) 1206 1207 key_numbers = vector["IUT"] 1208 private_numbers = ec.EllipticCurvePrivateNumbers( 1209 key_numbers["d"], 1210 ec.EllipticCurvePublicNumbers( 1211 key_numbers["x"], 1212 key_numbers["y"], 1213 ec._CURVE_TYPES[vector["curve"]](), 1214 ), 1215 ) 1216 # Errno 5-7 indicates a bad public or private key, this doesn't test 1217 # the ECDH code at all 1218 if vector["fail"] and vector["errno"] in [5, 6, 7]: 1219 with pytest.raises(ValueError): 1220 private_numbers.private_key(backend) 1221 return 1222 else: 1223 private_key = private_numbers.private_key(backend) 1224 1225 peer_numbers = vector["CAVS"] 1226 public_numbers = ec.EllipticCurvePublicNumbers( 1227 peer_numbers["x"], 1228 peer_numbers["y"], 1229 ec._CURVE_TYPES[vector["curve"]](), 1230 ) 1231 # Errno 1 and 2 indicates a bad public key, this doesn't test the ECDH 1232 # code at all 1233 if vector["fail"] and vector["errno"] in [1, 2]: 1234 with pytest.raises(ValueError): 1235 public_numbers.public_key(backend) 1236 return 1237 else: 1238 peer_pubkey = public_numbers.public_key(backend) 1239 1240 z = private_key.exchange(ec.ECDH(), peer_pubkey) 1241 z = int(hexlify(z).decode("ascii"), 16) 1242 # At this point fail indicates that one of the underlying keys was 1243 # changed. This results in a non-matching derived key. 1244 if vector["fail"]: 1245 # Errno 8 indicates Z should be changed. 1246 assert vector["errno"] == 8 1247 assert z != vector["Z"] 1248 else: 1249 assert z == vector["Z"] 1250 1251 @pytest.mark.parametrize( 1252 "vector", 1253 load_vectors_from_file( 1254 os.path.join("asymmetric", "ECDH", "brainpool.txt"), 1255 load_nist_vectors, 1256 ), 1257 ) 1258 def test_brainpool_kex(self, backend, vector): 1259 curve = ec._CURVE_TYPES[vector["curve"].decode("ascii")] 1260 _skip_exchange_algorithm_unsupported(backend, ec.ECDH(), curve) 1261 key = ec.EllipticCurvePrivateNumbers( 1262 int(vector["da"], 16), 1263 ec.EllipticCurvePublicNumbers( 1264 int(vector["x_qa"], 16), int(vector["y_qa"], 16), curve() 1265 ), 1266 ).private_key(backend) 1267 peer = ec.EllipticCurvePrivateNumbers( 1268 int(vector["db"], 16), 1269 ec.EllipticCurvePublicNumbers( 1270 int(vector["x_qb"], 16), int(vector["y_qb"], 16), curve() 1271 ), 1272 ).private_key(backend) 1273 shared_secret = key.exchange(ec.ECDH(), peer.public_key()) 1274 assert shared_secret == binascii.unhexlify(vector["x_z"]) 1275 shared_secret_2 = peer.exchange(ec.ECDH(), key.public_key()) 1276 assert shared_secret_2 == binascii.unhexlify(vector["x_z"]) 1277 1278 def test_exchange_unsupported_algorithm(self, backend): 1279 _skip_curve_unsupported(backend, ec.SECP256R1()) 1280 1281 key = load_vectors_from_file( 1282 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 1283 lambda pemfile: serialization.load_pem_private_key( 1284 pemfile.read().encode(), None, backend 1285 ), 1286 ) 1287 1288 with raises_unsupported_algorithm( 1289 exceptions._Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM 1290 ): 1291 key.exchange(None, key.public_key()) 1292 1293 def test_exchange_non_matching_curve(self, backend): 1294 _skip_curve_unsupported(backend, ec.SECP256R1()) 1295 _skip_curve_unsupported(backend, ec.SECP384R1()) 1296 1297 key = load_vectors_from_file( 1298 os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"), 1299 lambda pemfile: serialization.load_pem_private_key( 1300 pemfile.read().encode(), None, backend 1301 ), 1302 ) 1303 public_key = EC_KEY_SECP384R1.public_numbers.public_key(backend) 1304 1305 with pytest.raises(ValueError): 1306 key.exchange(ec.ECDH(), public_key) 1307