summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucia Li <luciali@google.com>2021-11-12 05:47:31 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-11-12 05:47:31 +0000
commit53de212301f5608092d47f07e3c93269da853a33 (patch)
tree1bc0942b942becc5391abbaf74cb61a05a4e76cd
parent18f3c12319b4404e3fdede4639e66c3cf8f28028 (diff)
parent5b1b2f5ab84c528c97d7246ecf96f6fe4b541fe7 (diff)
downloadcryptography-android13-mainline-go-sdkext-release.tar.gz
Upgrade cryptography from 2.5 to 3.3 am: c6ba99dd61 am: 59e6f3b36b am: 3be2d17c44 am: 5b1b2f5ab8t_frc_odp_330442040t_frc_odp_330442000t_frc_con_330443020t_frc_cbr_330443000t_frc_ase_330444010t_frc_art_330443060t_frc_adb_330444000android-13.0.0_r83android-13.0.0_r82android-13.0.0_r81android-13.0.0_r80android-13.0.0_r79android-13.0.0_r78android-13.0.0_r77android-13.0.0_r76android-13.0.0_r75android-13.0.0_r74android-13.0.0_r73android-13.0.0_r72android-13.0.0_r71android-13.0.0_r70android-13.0.0_r69android-13.0.0_r68android-13.0.0_r67android-13.0.0_r66android-13.0.0_r65android-13.0.0_r64android-13.0.0_r63android-13.0.0_r62android-13.0.0_r61android-13.0.0_r60android-13.0.0_r59android-13.0.0_r58android-13.0.0_r57android-13.0.0_r56android-13.0.0_r55android-13.0.0_r54android-13.0.0_r53android-13.0.0_r52android-13.0.0_r51android-13.0.0_r50android-13.0.0_r49android-13.0.0_r48android-13.0.0_r47android-13.0.0_r46android-13.0.0_r45android-13.0.0_r44android-13.0.0_r43android-13.0.0_r42android-13.0.0_r41android-13.0.0_r40android-13.0.0_r39android-13.0.0_r38android-13.0.0_r37android-13.0.0_r36android-13.0.0_r35android-13.0.0_r34android-13.0.0_r33android-13.0.0_r32android-13.0.0_r30android-13.0.0_r29android-13.0.0_r28android-13.0.0_r27android-13.0.0_r24android-13.0.0_r23android-13.0.0_r22android-13.0.0_r21android-13.0.0_r20android-13.0.0_r19android-13.0.0_r18android-13.0.0_r17android-13.0.0_r16aml_uwb_331910010aml_uwb_331820070aml_uwb_331613010aml_uwb_331611010aml_uwb_331410010aml_uwb_331310030aml_uwb_331115000aml_uwb_331015040aml_uwb_330810010aml_tz4_332714070aml_tz4_332714050aml_tz4_332714010aml_tz4_331910000aml_tz4_331314030aml_tz4_331314020aml_tz4_331314010aml_tz4_331012050aml_tz4_331012040aml_tz4_331012000aml_go_wif_330911000aml_go_uwb_330912000aml_go_tz4_330912000aml_go_tet_330914010aml_go_swc_330913000aml_go_sta_330911000aml_go_sdk_330810000aml_go_sch_330911000aml_go_res_330912000aml_go_per_330912000aml_go_odp_330913000aml_go_odp_330912000aml_go_neu_330912000aml_go_net_330913000aml_go_mpr_330912000aml_go_ase_330913000aml_go_ads_330915100aml_go_ads_330915000aml_go_ads_330913000aml_go_adb_330913000aml_ase_331311020aml_ase_331112000aml_ase_331011020aml_ads_331920180aml_ads_331814200aml_ads_331710270aml_ads_331611190aml_ads_331511020aml_ads_331418080aml_ads_331131000android13-qpr3-s9-releaseandroid13-qpr3-s8-releaseandroid13-qpr3-s7-releaseandroid13-qpr3-s6-releaseandroid13-qpr3-s5-releaseandroid13-qpr3-s4-releaseandroid13-qpr3-s3-releaseandroid13-qpr3-s2-releaseandroid13-qpr3-s14-releaseandroid13-qpr3-s13-releaseandroid13-qpr3-s12-releaseandroid13-qpr3-s11-releaseandroid13-qpr3-s10-releaseandroid13-qpr3-s1-releaseandroid13-qpr3-releaseandroid13-qpr3-c-s8-releaseandroid13-qpr3-c-s7-releaseandroid13-qpr3-c-s6-releaseandroid13-qpr3-c-s5-releaseandroid13-qpr3-c-s4-releaseandroid13-qpr3-c-s3-releaseandroid13-qpr3-c-s2-releaseandroid13-qpr3-c-s12-releaseandroid13-qpr3-c-s11-releaseandroid13-qpr3-c-s10-releaseandroid13-qpr3-c-s1-releaseandroid13-qpr2-s9-releaseandroid13-qpr2-s8-releaseandroid13-qpr2-s7-releaseandroid13-qpr2-s6-releaseandroid13-qpr2-s5-releaseandroid13-qpr2-s3-releaseandroid13-qpr2-s2-releaseandroid13-qpr2-s12-releaseandroid13-qpr2-s11-releaseandroid13-qpr2-s10-releaseandroid13-qpr2-s1-releaseandroid13-qpr2-releaseandroid13-qpr2-b-s1-releaseandroid13-qpr1-s8-releaseandroid13-qpr1-s7-releaseandroid13-qpr1-s6-releaseandroid13-qpr1-s5-releaseandroid13-qpr1-s4-releaseandroid13-qpr1-s3-releaseandroid13-qpr1-s2-releaseandroid13-qpr1-s1-releaseandroid13-qpr1-releaseandroid13-mainline-uwb-releaseandroid13-mainline-tzdata4-releaseandroid13-mainline-go-wifi-releaseandroid13-mainline-go-uwb-releaseandroid13-mainline-go-tzdata4-releaseandroid13-mainline-go-tethering-releaseandroid13-mainline-go-sdkext-releaseandroid13-mainline-go-scheduling-releaseandroid13-mainline-go-resolv-releaseandroid13-mainline-go-permission-releaseandroid13-mainline-go-os-statsd-releaseandroid13-mainline-go-odp-releaseandroid13-mainline-go-neuralnetworks-releaseandroid13-mainline-go-networking-releaseandroid13-mainline-go-mediaprovider-releaseandroid13-mainline-go-media-swcodec-releaseandroid13-mainline-go-appsearch-releaseandroid13-mainline-go-adservices-releaseandroid13-mainline-go-adbd-releaseandroid13-mainline-appsearch-releaseandroid13-mainline-adservices-releaseandroid13-frc-odp-releaseandroid13-frc-conscrypt-releaseandroid13-frc-cellbroadcast-releaseandroid13-frc-art-releaseandroid13-frc-adbd-releaseandroid13-devandroid13-d4-s2-releaseandroid13-d4-s1-releaseandroid13-d4-releaseandroid13-d3-s1-releaseandroid13-d2-releaseaml_tz4_332714010
Original change: https://android-review.googlesource.com/c/platform/external/python/cryptography/+/1888276 Change-Id: I312ce518598bb6d0e2ee4ec1649429e04b8958e1
-rw-r--r--CHANGELOG.rst298
-rw-r--r--Jenkinsfile247
-rw-r--r--LICENSE281
-rw-r--r--MANIFEST.in9
-rw-r--r--METADATA6
-rw-r--r--README.rst10
-rw-r--r--dev-requirements.txt2
-rw-r--r--docs/api-stability.rst2
-rw-r--r--docs/conf.py78
-rw-r--r--docs/development/c-bindings.rst6
-rw-r--r--docs/development/custom-vectors/arc4/generate_arc4.py51
-rw-r--r--docs/development/custom-vectors/cast5/generate_cast5.py47
-rw-r--r--docs/development/custom-vectors/hkdf/generate_hkdf.py30
-rw-r--r--docs/development/custom-vectors/idea/generate_idea.py8
-rw-r--r--docs/development/custom-vectors/idea/verify_idea.py17
-rw-r--r--docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py20
-rw-r--r--docs/development/custom-vectors/secp256k1/generate_secp256k1.py21
-rw-r--r--docs/development/custom-vectors/secp256k1/verify_secp256k1.py33
-rw-r--r--docs/development/custom-vectors/seed/generate_seed.py8
-rw-r--r--docs/development/custom-vectors/seed/verify_seed.py17
-rw-r--r--docs/development/getting-started.rst2
-rw-r--r--docs/development/reviewing-patches.rst12
-rw-r--r--docs/development/submitting-patches.rst16
-rw-r--r--docs/development/test-vectors.rst119
-rw-r--r--docs/doing-a-release.rst8
-rw-r--r--docs/faq.rst90
-rw-r--r--docs/fernet.rst53
-rw-r--r--docs/hazmat/backends/index.rst9
-rw-r--r--docs/hazmat/backends/interfaces.rst5
-rw-r--r--docs/hazmat/backends/openssl.rst10
-rw-r--r--docs/hazmat/bindings/index.rst22
-rw-r--r--docs/hazmat/bindings/openssl.rst48
-rw-r--r--docs/hazmat/primitives/asymmetric/dh.rst32
-rw-r--r--docs/hazmat/primitives/asymmetric/dsa.rst63
-rw-r--r--docs/hazmat/primitives/asymmetric/ec.rst107
-rw-r--r--docs/hazmat/primitives/asymmetric/ed25519.rst168
-rw-r--r--docs/hazmat/primitives/asymmetric/ed448.rst131
-rw-r--r--docs/hazmat/primitives/asymmetric/index.rst2
-rw-r--r--docs/hazmat/primitives/asymmetric/rsa.rst85
-rw-r--r--docs/hazmat/primitives/asymmetric/serialization.rst382
-rw-r--r--docs/hazmat/primitives/asymmetric/utils.rst2
-rw-r--r--docs/hazmat/primitives/asymmetric/x25519.rst3
-rw-r--r--docs/hazmat/primitives/asymmetric/x448.rst3
-rw-r--r--docs/hazmat/primitives/cryptographic-hashes.rst7
-rw-r--r--docs/hazmat/primitives/key-derivation-functions.rst555
-rw-r--r--docs/hazmat/primitives/keywrap.rst16
-rw-r--r--docs/hazmat/primitives/mac/cmac.rst9
-rw-r--r--docs/hazmat/primitives/mac/hmac.rst9
-rw-r--r--docs/hazmat/primitives/mac/index.rst41
-rw-r--r--docs/hazmat/primitives/mac/poly1305.rst132
-rw-r--r--docs/hazmat/primitives/padding.rst3
-rw-r--r--docs/hazmat/primitives/symmetric-encryption.rst37
-rw-r--r--docs/hazmat/primitives/twofactor.rst20
-rw-r--r--docs/index.rst5
-rw-r--r--docs/installation.rst54
-rw-r--r--docs/limitations.rst45
-rw-r--r--docs/security.rst19
-rw-r--r--docs/spelling_wordlist.txt11
-rw-r--r--docs/x509/ocsp.rst45
-rw-r--r--docs/x509/reference.rst463
-rw-r--r--docs/x509/tutorial.rst11
-rw-r--r--pyproject.toml13
-rw-r--r--release.py148
-rw-r--r--setup.py387
-rw-r--r--src/_cffi_src/build_constant_time.py27
-rw-r--r--src/_cffi_src/build_openssl.py64
-rw-r--r--src/_cffi_src/build_padding.py12
-rw-r--r--src/_cffi_src/hazmat_src/constant_time.c22
-rw-r--r--src/_cffi_src/hazmat_src/constant_time.h6
-rw-r--r--src/_cffi_src/openssl/aes.py11
-rw-r--r--src/_cffi_src/openssl/asn1.py6
-rw-r--r--src/_cffi_src/openssl/bignum.py1
-rw-r--r--src/_cffi_src/openssl/bio.py7
-rw-r--r--src/_cffi_src/openssl/callbacks.py118
-rw-r--r--src/_cffi_src/openssl/cmac.py2
-rw-r--r--src/_cffi_src/openssl/crypto.py40
-rw-r--r--src/_cffi_src/openssl/cryptography.py31
-rw-r--r--src/_cffi_src/openssl/ct.py19
-rw-r--r--src/_cffi_src/openssl/dh.py81
-rw-r--r--src/_cffi_src/openssl/dsa.py66
-rw-r--r--src/_cffi_src/openssl/ec.py13
-rw-r--r--src/_cffi_src/openssl/ecdh.py10
-rw-r--r--src/_cffi_src/openssl/ecdsa.py9
-rw-r--r--src/_cffi_src/openssl/engine.py132
-rw-r--r--src/_cffi_src/openssl/err.py147
-rw-r--r--src/_cffi_src/openssl/evp.py90
-rw-r--r--src/_cffi_src/openssl/hmac.py26
-rw-r--r--src/_cffi_src/openssl/nid.py226
-rw-r--r--src/_cffi_src/openssl/objects.py8
-rw-r--r--src/_cffi_src/openssl/ocsp.py12
-rw-r--r--src/_cffi_src/openssl/pem.py14
-rw-r--r--src/_cffi_src/openssl/pkcs7.py26
-rw-r--r--src/_cffi_src/openssl/rand.py7
-rw-r--r--src/_cffi_src/openssl/rsa.py129
-rw-r--r--src/_cffi_src/openssl/src/osrandom_engine.c50
-rw-r--r--src/_cffi_src/openssl/src/osrandom_engine.h21
-rw-r--r--src/_cffi_src/openssl/ssl.py291
-rw-r--r--src/_cffi_src/openssl/x509.py172
-rw-r--r--src/_cffi_src/openssl/x509_vfy.py98
-rw-r--r--src/_cffi_src/openssl/x509name.py11
-rw-r--r--src/_cffi_src/openssl/x509v3.py3
-rw-r--r--src/_cffi_src/utils.py44
-rw-r--r--src/cryptography/Android.bp8
-rw-r--r--src/cryptography/__about__.py20
-rw-r--r--src/cryptography/__init__.py33
-rw-r--r--src/cryptography/exceptions.py1
-rw-r--r--src/cryptography/fernet.py39
-rw-r--r--src/cryptography/hazmat/_der.py156
-rw-r--r--src/cryptography/hazmat/_oid.py34
-rw-r--r--src/cryptography/hazmat/backends/__init__.py8
-rw-r--r--src/cryptography/hazmat/backends/interfaces.py9
-rw-r--r--src/cryptography/hazmat/backends/openssl/aead.py33
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py1410
-rw-r--r--src/cryptography/hazmat/backends/openssl/ciphers.py134
-rw-r--r--src/cryptography/hazmat/backends/openssl/cmac.py32
-rw-r--r--src/cryptography/hazmat/backends/openssl/decode_asn1.py260
-rw-r--r--src/cryptography/hazmat/backends/openssl/dh.py123
-rw-r--r--src/cryptography/hazmat/backends/openssl/dsa.py39
-rw-r--r--src/cryptography/hazmat/backends/openssl/ec.py91
-rw-r--r--src/cryptography/hazmat/backends/openssl/ed25519.py145
-rw-r--r--src/cryptography/hazmat/backends/openssl/ed448.py146
-rw-r--r--src/cryptography/hazmat/backends/openssl/encode_asn1.py100
-rw-r--r--src/cryptography/hazmat/backends/openssl/hashes.py34
-rw-r--r--src/cryptography/hazmat/backends/openssl/hmac.py31
-rw-r--r--src/cryptography/hazmat/backends/openssl/ocsp.py74
-rw-r--r--src/cryptography/hazmat/backends/openssl/poly1305.py65
-rw-r--r--src/cryptography/hazmat/backends/openssl/rsa.py270
-rw-r--r--src/cryptography/hazmat/backends/openssl/utils.py15
-rw-r--r--src/cryptography/hazmat/backends/openssl/x25519.py74
-rw-r--r--src/cryptography/hazmat/backends/openssl/x448.py48
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py157
-rw-r--r--src/cryptography/hazmat/bindings/_constant_time.sobin26832 -> 0 bytes
-rwxr-xr-x[-rw-r--r--]src/cryptography/hazmat/bindings/_openssl.sobin5709758 -> 2519552 bytes
-rwxr-xr-x[-rw-r--r--]src/cryptography/hazmat/bindings/_padding.sobin28951 -> 33048 bytes
-rw-r--r--src/cryptography/hazmat/bindings/openssl/_conditional.py235
-rw-r--r--src/cryptography/hazmat/bindings/openssl/binding.py108
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/dh.py46
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/dsa.py37
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/ec.py87
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/ed25519.py87
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/ed448.py82
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/padding.py9
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/rsa.py94
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/utils.py51
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/x25519.py11
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/x448.py9
-rw-r--r--src/cryptography/hazmat/primitives/ciphers/__init__.py9
-rw-r--r--src/cryptography/hazmat/primitives/ciphers/aead.py30
-rw-r--r--src/cryptography/hazmat/primitives/ciphers/algorithms.py11
-rw-r--r--src/cryptography/hazmat/primitives/ciphers/base.py22
-rw-r--r--src/cryptography/hazmat/primitives/ciphers/modes.py33
-rw-r--r--src/cryptography/hazmat/primitives/cmac.py21
-rw-r--r--src/cryptography/hazmat/primitives/constant_time.py29
-rw-r--r--src/cryptography/hazmat/primitives/hashes.py10
-rw-r--r--src/cryptography/hazmat/primitives/hmac.py15
-rw-r--r--src/cryptography/hazmat/primitives/kdf/concatkdf.py35
-rw-r--r--src/cryptography/hazmat/primitives/kdf/hkdf.py23
-rw-r--r--src/cryptography/hazmat/primitives/kdf/kbkdf.py45
-rw-r--r--src/cryptography/hazmat/primitives/kdf/pbkdf2.py20
-rw-r--r--src/cryptography/hazmat/primitives/kdf/scrypt.py11
-rw-r--r--src/cryptography/hazmat/primitives/kdf/x963kdf.py18
-rw-r--r--src/cryptography/hazmat/primitives/keywrap.py37
-rw-r--r--src/cryptography/hazmat/primitives/mac.py37
-rw-r--r--src/cryptography/hazmat/primitives/padding.py50
-rw-r--r--src/cryptography/hazmat/primitives/poly1305.py58
-rw-r--r--src/cryptography/hazmat/primitives/serialization/__init__.py40
-rw-r--r--src/cryptography/hazmat/primitives/serialization/base.py21
-rw-r--r--src/cryptography/hazmat/primitives/serialization/pkcs12.py43
-rw-r--r--src/cryptography/hazmat/primitives/serialization/pkcs7.py132
-rw-r--r--src/cryptography/hazmat/primitives/serialization/ssh.py731
-rw-r--r--src/cryptography/hazmat/primitives/twofactor/hotp.py23
-rw-r--r--src/cryptography/hazmat/primitives/twofactor/totp.py29
-rw-r--r--src/cryptography/hazmat/primitives/twofactor/utils.py7
-rw-r--r--src/cryptography/utils.py40
-rw-r--r--src/cryptography/x509/__init__.py105
-rw-r--r--src/cryptography/x509/base.py353
-rw-r--r--src/cryptography/x509/extensions.py610
-rw-r--r--src/cryptography/x509/general_name.py94
-rw-r--r--src/cryptography/x509/name.py87
-rw-r--r--src/cryptography/x509/ocsp.py121
-rw-r--r--src/cryptography/x509/oid.py60
-rw-r--r--tests/conftest.py21
-rw-r--r--tests/hazmat/backends/test_no_backend.py16
-rw-r--r--tests/hazmat/backends/test_openssl.py309
-rw-r--r--tests/hazmat/backends/test_openssl_memleak.py255
-rw-r--r--tests/hazmat/bindings/test_openssl.py27
-rw-r--r--tests/hazmat/primitives/fixtures_dh.py26
-rw-r--r--tests/hazmat/primitives/fixtures_dsa.py217
-rw-r--r--tests/hazmat/primitives/fixtures_ec.py266
-rw-r--r--tests/hazmat/primitives/fixtures_rsa.py477
-rw-r--r--tests/hazmat/primitives/test_3des.py50
-rw-r--r--tests/hazmat/primitives/test_aead.py102
-rw-r--r--tests/hazmat/primitives/test_aes.py283
-rw-r--r--tests/hazmat/primitives/test_aes_gcm.py219
-rw-r--r--tests/hazmat/primitives/test_arc4.py2
-rw-r--r--tests/hazmat/primitives/test_asym_utils.py28
-rw-r--r--tests/hazmat/primitives/test_block.py32
-rw-r--r--tests/hazmat/primitives/test_blowfish.py8
-rw-r--r--tests/hazmat/primitives/test_camellia.py14
-rw-r--r--tests/hazmat/primitives/test_cast5.py14
-rw-r--r--tests/hazmat/primitives/test_chacha20.py8
-rw-r--r--tests/hazmat/primitives/test_ciphers.py116
-rw-r--r--tests/hazmat/primitives/test_cmac.py78
-rw-r--r--tests/hazmat/primitives/test_concatkdf.py73
-rw-r--r--tests/hazmat/primitives/test_dh.py575
-rw-r--r--tests/hazmat/primitives/test_dsa.py349
-rw-r--r--tests/hazmat/primitives/test_ec.py571
-rw-r--r--tests/hazmat/primitives/test_ed25519.py232
-rw-r--r--tests/hazmat/primitives/test_ed448.py256
-rw-r--r--tests/hazmat/primitives/test_hash_vectors.py135
-rw-r--r--tests/hazmat/primitives/test_hashes.py32
-rw-r--r--tests/hazmat/primitives/test_hkdf.py123
-rw-r--r--tests/hazmat/primitives/test_hkdf_vectors.py12
-rw-r--r--tests/hazmat/primitives/test_hmac.py20
-rw-r--r--tests/hazmat/primitives/test_hmac_vectors.py30
-rw-r--r--tests/hazmat/primitives/test_idea.py14
-rw-r--r--tests/hazmat/primitives/test_kbkdf.py327
-rw-r--r--tests/hazmat/primitives/test_kbkdf_vectors.py4
-rw-r--r--tests/hazmat/primitives/test_keywrap.py38
-rw-r--r--tests/hazmat/primitives/test_padding.py204
-rw-r--r--tests/hazmat/primitives/test_pbkdf2hmac.py35
-rw-r--r--tests/hazmat/primitives/test_pbkdf2hmac_vectors.py4
-rw-r--r--tests/hazmat/primitives/test_pkcs12.py202
-rw-r--r--tests/hazmat/primitives/test_pkcs7.py675
-rw-r--r--tests/hazmat/primitives/test_poly1305.py156
-rw-r--r--tests/hazmat/primitives/test_rsa.py1326
-rw-r--r--tests/hazmat/primitives/test_scrypt.py105
-rw-r--r--tests/hazmat/primitives/test_seed.py14
-rw-r--r--tests/hazmat/primitives/test_serialization.py1459
-rw-r--r--tests/hazmat/primitives/test_x25519.py111
-rw-r--r--tests/hazmat/primitives/test_x448.py99
-rw-r--r--tests/hazmat/primitives/test_x963_vectors.py28
-rw-r--r--tests/hazmat/primitives/test_x963kdf.py34
-rw-r--r--tests/hazmat/primitives/twofactor/test_hotp.py17
-rw-r--r--tests/hazmat/primitives/twofactor/test_totp.py45
-rw-r--r--tests/hazmat/primitives/utils.py171
-rw-r--r--tests/hazmat/test_der.py232
-rw-r--r--tests/hazmat/test_oid.py39
-rw-r--r--tests/test_cryptography_utils.py5
-rw-r--r--tests/test_fernet.py66
-rw-r--r--tests/test_interfaces.py4
-rw-r--r--tests/test_utils.py3339
-rw-r--r--tests/test_warnings.py4
-rw-r--r--tests/utils.py195
-rw-r--r--tests/wycheproof/test_aes.py42
-rw-r--r--tests/wycheproof/test_chacha20poly1305.py2
-rw-r--r--tests/wycheproof/test_dsa.py10
-rw-r--r--tests/wycheproof/test_ecdh.py1
-rw-r--r--tests/wycheproof/test_ecdsa.py28
-rw-r--r--tests/wycheproof/test_eddsa.py63
-rw-r--r--tests/wycheproof/test_hkdf.py50
-rw-r--r--tests/wycheproof/test_hmac.py66
-rw-r--r--tests/wycheproof/test_keywrap.py8
-rw-r--r--tests/wycheproof/test_rsa.py159
-rw-r--r--tests/wycheproof/test_utils.py15
-rw-r--r--tests/wycheproof/test_x25519.py12
-rw-r--r--tests/wycheproof/test_x448.py50
-rw-r--r--tests/x509/test_ocsp.py603
-rw-r--r--tests/x509/test_x509.py4233
-rw-r--r--tests/x509/test_x509_crlbuilder.py673
-rw-r--r--tests/x509/test_x509_ext.py3668
-rw-r--r--tests/x509/test_x509_revokedcertbuilder.py72
-rw-r--r--tox.ini37
-rw-r--r--vectors/cryptography_vectors/__about__.py14
-rw-r--r--vectors/cryptography_vectors/__init__.py20
-rw-r--r--vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.derbin0 -> 830 bytes
-rw-r--r--vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_no_params.derbin0 -> 280 bytes
-rw-r--r--vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem4
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.derbin0 -> 158 bytes
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.pem6
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.derbin0 -> 48 bytes
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.pem3
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.derbin0 -> 44 bytes
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.pem3
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.derbin0 -> 174 bytes
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.pem6
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.derbin0 -> 73 bytes
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.pem4
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.derbin0 -> 69 bytes
-rw-r--r--vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.pem4
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key21
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key-cert.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key22
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key9
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key-cert.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key11
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key7
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key-cert.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key8
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key.pub1
-rwxr-xr-xvectors/cryptography_vectors/asymmetric/OpenSSH/gen.sh62
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key27
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key-cert.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key28
-rw-r--r--vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key.pub1
-rw-r--r--vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem36
-rw-r--r--vectors/cryptography_vectors/ciphers/Blowfish/bf-cbc.txt2
-rw-r--r--vectors/cryptography_vectors/ciphers/Blowfish/bf-cfb.txt2
-rw-r--r--vectors/cryptography_vectors/ciphers/Blowfish/bf-ecb.txt2
-rw-r--r--vectors/cryptography_vectors/ciphers/Blowfish/bf-ofb.txt2
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_224LongMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_224Monte.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_224ShortMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_256LongMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_256Monte.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_256ShortMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_384LongMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_384Monte.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_384ShortMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_512LongMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_512Monte.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHA3/SHA3_512ShortMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHAKE/SHAKE128LongMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHAKE/SHAKE128Monte.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHAKE/SHAKE128ShortMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHAKE/SHAKE128VariableOut.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHAKE/SHAKE256LongMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHAKE/SHAKE256Monte.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHAKE/SHAKE256ShortMsg.rsp0
-rw-r--r--[-rwxr-xr-x]vectors/cryptography_vectors/hashes/SHAKE/SHAKE256VariableOut.rsp0
-rw-r--r--vectors/cryptography_vectors/pkcs7/amazon-roots.p7bbin0 -> 1848 bytes
-rw-r--r--vectors/cryptography_vectors/pkcs7/enveloped.pem91
-rw-r--r--vectors/cryptography_vectors/pkcs7/isrg.pem33
-rw-r--r--vectors/cryptography_vectors/poly1305/rfc7539.txt56
-rw-r--r--vectors/cryptography_vectors/x509/custom/ca/rsa_ca.pem28
-rw-r--r--vectors/cryptography_vectors/x509/custom/ca/rsa_key.pem52
-rw-r--r--vectors/cryptography_vectors/x509/custom/crl_delta_crl_indicator.pem18
-rw-r--r--vectors/cryptography_vectors/x509/custom/negative_serial.pem25
-rw-r--r--vectors/cryptography_vectors/x509/custom/rsa_pss.pem20
-rw-r--r--vectors/cryptography_vectors/x509/custom/sia.pem18
-rw-r--r--vectors/cryptography_vectors/x509/ed25519/ed25519-rfc8410.pem9
-rw-r--r--vectors/cryptography_vectors/x509/ed25519/root-ed25519.pem9
-rw-r--r--vectors/cryptography_vectors/x509/ed25519/server-ed25519-cert.pem14
-rw-r--r--vectors/cryptography_vectors/x509/ed448/root-ed448.pem11
-rw-r--r--vectors/cryptography_vectors/x509/ed448/server-ed448-cert.pem14
-rw-r--r--vectors/cryptography_vectors/x509/ocsp/ocsp-army.deps.mil-resp.derbin0 -> 3587 bytes
-rw-r--r--vectors/cryptography_vectors/x509/ocsp/resp-sct-extension.derbin0 -> 2125 bytes
-rw-r--r--vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.derbin0 -> 280 bytes
-rw-r--r--vectors/cryptography_vectors/x509/requests/challenge-invalid.derbin0 -> 633 bytes
-rw-r--r--vectors/cryptography_vectors/x509/requests/challenge-unstructured.pem17
-rw-r--r--vectors/cryptography_vectors/x509/requests/challenge.pem16
-rw-r--r--vectors/setup.cfg2
-rw-r--r--vectors/setup.py6
349 files changed, 24032 insertions, 14542 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 7ee6d4d93..4dd714600 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,300 @@
Changelog
=========
+.. _v3-3-2:
+
+3.3.2 - 2021-02-07
+~~~~~~~~~~~~~~~~~~
+
+* **SECURITY ISSUE:** Fixed a bug where certain sequences of ``update()`` calls
+ when symmetrically encrypting very large payloads (>2GB) could result in an
+ integer overflow, leading to buffer overflows. *CVE-2020-36242*
+
+.. _v3-3-1:
+
+3.3.1 - 2020-12-09
+~~~~~~~~~~~~~~~~~~
+
+* Re-added a legacy symbol causing problems for older ``pyOpenSSL`` users.
+
+.. _v3-3:
+
+3.3 - 2020-12-08
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Support for Python 3.5 has been removed due to
+ low usage and maintenance burden.
+* **BACKWARDS INCOMPATIBLE:** The
+ :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` and
+ :class:`~cryptography.hazmat.primitives.ciphers.aead.AESGCM` now require
+ 64-bit to 1024-bit (8 byte to 128 byte) initialization vectors. This change
+ is to conform with an upcoming OpenSSL release that will no longer support
+ sizes outside this window.
+* **BACKWARDS INCOMPATIBLE:** When deserializing asymmetric keys we now
+ raise ``ValueError`` rather than ``UnsupportedAlgorithm`` when an
+ unsupported cipher is used. This change is to conform with an upcoming
+ OpenSSL release that will no longer distinguish between error types.
+* **BACKWARDS INCOMPATIBLE:** We no longer allow loading of finite field
+ Diffie-Hellman parameters of less than 512 bits in length. This change is to
+ conform with an upcoming OpenSSL release that no longer supports smaller
+ sizes. These keys were already wildly insecure and should not have been used
+ in any application outside of testing.
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+ OpenSSL 1.1.1i.
+* Python 2 support is deprecated in ``cryptography``. This is the last release
+ that will support Python 2.
+* Added the
+ :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.recover_data_from_signature`
+ function to
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
+ for recovering the signed data from an RSA signature.
+
+.. _v3-2-1:
+
+3.2.1 - 2020-10-27
+~~~~~~~~~~~~~~~~~~
+
+* Disable blinding on RSA public keys to address an error with some versions
+ of OpenSSL.
+
+.. _v3-2:
+
+3.2 - 2020-10-25
+~~~~~~~~~~~~~~~~
+
+* **SECURITY ISSUE:** Attempted to make RSA PKCS#1v1.5 decryption more constant
+ time, to protect against Bleichenbacher vulnerabilities. Due to limitations
+ imposed by our API, we cannot completely mitigate this vulnerability and a
+ future release will contain a new API which is designed to be resilient to
+ these for contexts where it is required. Credit to **Hubert Kario** for
+ reporting the issue. *CVE-2020-25659*
+* Support for OpenSSL 1.0.2 has been removed. Users on older version of OpenSSL
+ will need to upgrade.
+* Added basic support for PKCS7 signing (including SMIME) via
+ :class:`~cryptography.hazmat.primitives.serialization.pkcs7.PKCS7SignatureBuilder`.
+
+.. _v3-1-1:
+
+3.1.1 - 2020-09-22
+~~~~~~~~~~~~~~~~~~
+
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+ OpenSSL 1.1.1h.
+
+.. _v3-1:
+
+3.1 - 2020-08-26
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Removed support for ``idna`` based
+ :term:`U-label` parsing in various X.509 classes. This support was originally
+ deprecated in version 2.1 and moved to an extra in 2.5.
+* Deprecated OpenSSL 1.0.2 support. OpenSSL 1.0.2 is no longer supported by
+ the OpenSSL project. The next version of ``cryptography`` will drop support
+ for it.
+* Deprecated support for Python 3.5. This version sees very little use and will
+ be removed in the next release.
+* ``backend`` arguments to functions are no longer required and the
+ default backend will automatically be selected if no ``backend`` is provided.
+* Added initial support for parsing certificates from PKCS7 files with
+ :func:`~cryptography.hazmat.primitives.serialization.pkcs7.load_pem_pkcs7_certificates`
+ and
+ :func:`~cryptography.hazmat.primitives.serialization.pkcs7.load_der_pkcs7_certificates`
+ .
+* Calling ``update`` or ``update_into`` on
+ :class:`~cryptography.hazmat.primitives.ciphers.CipherContext` with ``data``
+ longer than 2\ :sup:`31` bytes no longer raises an ``OverflowError``. This
+ also resolves the same issue in :doc:`/fernet`.
+
+.. _v3-0:
+
+3.0 - 2020-07-20
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Removed support for passing an
+ :class:`~cryptography.x509.Extension` instance to
+ :meth:`~cryptography.x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier`,
+ as per our deprecation policy.
+* **BACKWARDS INCOMPATIBLE:** Support for LibreSSL 2.7.x, 2.8.x, and 2.9.0 has
+ been removed (2.9.1+ is still supported).
+* **BACKWARDS INCOMPATIBLE:** Dropped support for macOS 10.9, macOS users must
+ upgrade to 10.10 or newer.
+* **BACKWARDS INCOMPATIBLE:** RSA
+ :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key`
+ no longer accepts ``public_exponent`` values except 65537 and 3 (the latter
+ for legacy purposes).
+* **BACKWARDS INCOMPATIBLE:** X.509 certificate parsing now enforces that the
+ ``version`` field contains a valid value, rather than deferring this check
+ until :attr:`~cryptography.x509.Certificate.version` is accessed.
+* Deprecated support for Python 2. At the time there is no time table for
+ actually dropping support, however we strongly encourage all users to upgrade
+ their Python, as Python 2 no longer receives support from the Python core
+ team.
+
+ If you have trouble suppressing this warning in tests view the :ref:`FAQ
+ entry addressing this issue <faq-howto-handle-deprecation-warning>`.
+
+* Added support for ``OpenSSH`` serialization format for
+ ``ec``, ``ed25519``, ``rsa`` and ``dsa`` private keys:
+ :func:`~cryptography.hazmat.primitives.serialization.load_ssh_private_key`
+ for loading and
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
+ for writing.
+* Added support for ``OpenSSH`` certificates to
+ :func:`~cryptography.hazmat.primitives.serialization.load_ssh_public_key`.
+* Added :meth:`~cryptography.fernet.Fernet.encrypt_at_time` and
+ :meth:`~cryptography.fernet.Fernet.decrypt_at_time` to
+ :class:`~cryptography.fernet.Fernet`.
+* Added support for the :class:`~cryptography.x509.SubjectInformationAccess`
+ X.509 extension.
+* Added support for parsing
+ :class:`~cryptography.x509.SignedCertificateTimestamps` in OCSP responses.
+* Added support for parsing attributes in certificate signing requests via
+ :meth:`~cryptography.x509.CertificateSigningRequest.get_attribute_for_oid`.
+* Added support for encoding attributes in certificate signing requests via
+ :meth:`~cryptography.x509.CertificateSigningRequestBuilder.add_attribute`.
+* On OpenSSL 1.1.1d and higher ``cryptography`` now uses OpenSSL's
+ built-in CSPRNG instead of its own OS random engine because these versions of
+ OpenSSL properly reseed on fork.
+* Added initial support for creating PKCS12 files with
+ :func:`~cryptography.hazmat.primitives.serialization.pkcs12.serialize_key_and_certificates`.
+
+.. _v2-9-2:
+
+2.9.2 - 2020-04-22
+~~~~~~~~~~~~~~~~~~
+
+* Updated the macOS wheel to fix an issue where it would not run on macOS
+ versions older than 10.15.
+
+.. _v2-9-1:
+
+2.9.1 - 2020-04-21
+~~~~~~~~~~~~~~~~~~
+
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+ OpenSSL 1.1.1g.
+
+.. _v2-9:
+
+2.9 - 2020-04-02
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Support for Python 3.4 has been removed due to
+ low usage and maintenance burden.
+* **BACKWARDS INCOMPATIBLE:** Support for OpenSSL 1.0.1 has been removed.
+ Users on older version of OpenSSL will need to upgrade.
+* **BACKWARDS INCOMPATIBLE:** Support for LibreSSL 2.6.x has been removed.
+* Removed support for calling
+ :meth:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PublicKey.public_bytes`
+ with no arguments, as per our deprecation policy. You must now pass
+ ``encoding`` and ``format``.
+* **BACKWARDS INCOMPATIBLE:** Reversed the order in which
+ :meth:`~cryptography.x509.Name.rfc4514_string` returns the RDNs
+ as required by :rfc:`4514`.
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+ OpenSSL 1.1.1f.
+* Added support for parsing
+ :attr:`~cryptography.x509.ocsp.OCSPResponse.single_extensions` in an OCSP
+ response.
+* :class:`~cryptography.x509.NameAttribute` values can now be empty strings.
+
+.. _v2-8:
+
+2.8 - 2019-10-16
+~~~~~~~~~~~~~~~~
+
+* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with
+ OpenSSL 1.1.1d.
+* Added support for Python 3.8.
+* Added class methods
+ :meth:`Poly1305.generate_tag
+ <cryptography.hazmat.primitives.poly1305.Poly1305.generate_tag>`
+ and
+ :meth:`Poly1305.verify_tag
+ <cryptography.hazmat.primitives.poly1305.Poly1305.verify_tag>`
+ for Poly1305 sign and verify operations.
+* Deprecated support for OpenSSL 1.0.1. Support will be removed in
+ ``cryptography`` 2.9.
+* We now ship ``manylinux2010`` wheels in addition to our ``manylinux1``
+ wheels.
+* Added support for ``ed25519`` and ``ed448`` keys in the
+ :class:`~cryptography.x509.CertificateBuilder`,
+ :class:`~cryptography.x509.CertificateSigningRequestBuilder`,
+ :class:`~cryptography.x509.CertificateRevocationListBuilder` and
+ :class:`~cryptography.x509.ocsp.OCSPResponseBuilder`.
+* ``cryptography`` no longer depends on ``asn1crypto``.
+* :class:`~cryptography.x509.FreshestCRL` is now allowed as a
+ :class:`~cryptography.x509.CertificateRevocationList` extension.
+
+.. _v2-7:
+
+2.7 - 2019-05-30
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** We no longer distribute 32-bit ``manylinux1``
+ wheels. Continuing to produce them was a maintenance burden.
+* **BACKWARDS INCOMPATIBLE:** Removed the
+ ``cryptography.hazmat.primitives.mac.MACContext`` interface. The ``CMAC`` and
+ ``HMAC`` APIs have not changed, but they are no longer registered as
+ ``MACContext`` instances.
+* Updated Windows, macOS, and ``manylinux1`` wheels to be compiled with
+ OpenSSL 1.1.1c.
+* Removed support for running our tests with ``setup.py test``. Users
+ interested in running our tests can continue to follow the directions in our
+ :doc:`development documentation</development/getting-started>`.
+* Add support for :class:`~cryptography.hazmat.primitives.poly1305.Poly1305`
+ when using OpenSSL 1.1.1 or newer.
+* Support serialization with ``Encoding.OpenSSH`` and ``PublicFormat.OpenSSH``
+ in
+ :meth:`Ed25519PublicKey.public_bytes
+ <cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey.public_bytes>`
+ .
+* Correctly allow passing a ``SubjectKeyIdentifier`` to
+ :meth:`~cryptography.x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier`
+ and deprecate passing an ``Extension`` object. The documentation always
+ required ``SubjectKeyIdentifier`` but the implementation previously
+ required an ``Extension``.
+
+.. _v2-6-1:
+
+2.6.1 - 2019-02-27
+~~~~~~~~~~~~~~~~~~
+
+* Resolved an error in our build infrastructure that broke our Python3 wheels
+ for macOS and Linux.
+
+.. _v2-6:
+
+2.6 - 2019-02-27
+~~~~~~~~~~~~~~~~
+
+* **BACKWARDS INCOMPATIBLE:** Removed
+ ``cryptography.hazmat.primitives.asymmetric.utils.encode_rfc6979_signature``
+ and
+ ``cryptography.hazmat.primitives.asymmetric.utils.decode_rfc6979_signature``,
+ which had been deprecated for nearly 4 years. Use
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`
+ and
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`
+ instead.
+* **BACKWARDS INCOMPATIBLE**: Removed ``cryptography.x509.Certificate.serial``,
+ which had been deprecated for nearly 3 years. Use
+ :attr:`~cryptography.x509.Certificate.serial_number` instead.
+* Updated Windows, macOS, and ``manylinux1`` wheels to be compiled with
+ OpenSSL 1.1.1b.
+* Added support for :doc:`/hazmat/primitives/asymmetric/ed448` when using
+ OpenSSL 1.1.1b or newer.
+* Added support for :doc:`/hazmat/primitives/asymmetric/ed25519` when using
+ OpenSSL 1.1.1b or newer.
+* :func:`~cryptography.hazmat.primitives.serialization.load_ssh_public_key` can
+ now load ``ed25519`` public keys.
+* Add support for easily mapping an object identifier to its elliptic curve
+ class via
+ :func:`~cryptography.hazmat.primitives.asymmetric.ec.get_curve_for_oid`.
+* Add support for OpenSSL when compiled with the ``no-engine``
+ (``OPENSSL_NO_ENGINE``) flag.
+
.. _v2-5:
2.5 - 2019-01-22
@@ -1099,8 +1393,8 @@ Changelog
:class:`~cryptography.fernet.MultiFernet`.
* More bit-lengths are now supported for ``p`` and ``q`` when loading DSA keys
from numbers.
-* Added :class:`~cryptography.hazmat.primitives.mac.MACContext` as a
- common interface for CMAC and HMAC and deprecated ``CMACContext``.
+* Added ``MACContext`` as a common interface for CMAC and HMAC and
+ deprecated ``CMACContext``.
* Added support for encoding and decoding :rfc:`6979` signatures in
:doc:`/hazmat/primitives/asymmetric/utils`.
* Added
diff --git a/Jenkinsfile b/Jenkinsfile
deleted file mode 100644
index 14a1ed7fd..000000000
--- a/Jenkinsfile
+++ /dev/null
@@ -1,247 +0,0 @@
-if (env.BRANCH_NAME == "master") {
- properties([pipelineTriggers([cron('@daily')])])
-}
-
-def configs = [
- [
- label: 'windows',
- toxenvs: ['py27', 'py34', 'py35', 'py36', 'py37'],
- ],
- [
- label: 'windows64',
- toxenvs: ['py27', 'py34', 'py35', 'py36', 'py37'],
- ],
- [
- label: 'sierra',
- toxenvs: ['py27', 'py36'],
- ],
- [
- label: 'yosemite',
- toxenvs: ['py27'],
- ],
- [
- label: 'docker',
- imageName: 'pyca/cryptography-runner-sid',
- toxenvs: ['docs'],
- artifacts: 'cryptography/docs/_build/html/**',
- artifactExcludes: '**/*.doctree',
- ],
-]
-
-def checkout_git(label) {
- retry(3) {
- def script = ""
- if (env.BRANCH_NAME.startsWith('PR-')) {
- script = """
- git clone --depth=1 https://github.com/pyca/cryptography
- cd cryptography
- git fetch origin +refs/pull/${env.CHANGE_ID}/merge:
- git checkout -qf FETCH_HEAD
- """
- if (label.contains("windows")) {
- bat script
- } else {
- sh """#!/bin/sh
- set -xe
- ${script}
- """
- }
- } else {
- checkout([
- $class: 'GitSCM',
- branches: [[name: "*/${env.BRANCH_NAME}"]],
- doGenerateSubmoduleConfigurations: false,
- extensions: [[
- $class: 'RelativeTargetDirectory',
- relativeTargetDir: 'cryptography'
- ]],
- submoduleCfg: [],
- userRemoteConfigs: [[
- 'url': 'https://github.com/pyca/cryptography'
- ]]
- ])
- }
- }
- if (label.contains("windows")) {
- bat """
- cd cryptography
- git rev-parse HEAD
- """
- } else {
- sh """
- cd cryptography
- git rev-parse HEAD
- """
- }
-}
-def build(toxenv, label, imageName, artifacts, artifactExcludes) {
- try {
- timeout(time: 30, unit: 'MINUTES') {
-
- checkout_git(label)
- checkout([
- $class: 'GitSCM',
- extensions: [[
- $class: 'RelativeTargetDirectory',
- relativeTargetDir: 'wycheproof',
- ]],
- userRemoteConfigs: [[
- 'url': 'https://github.com/google/wycheproof',
- ]]
- ])
-
- withCredentials([string(credentialsId: 'cryptography-codecov-token', variable: 'CODECOV_TOKEN')]) {
- withEnv(["LABEL=$label", "TOXENV=$toxenv", "IMAGE_NAME=$imageName"]) {
- if (label.contains("windows")) {
- def pythonPath = [
- py27: "C:\\Python27\\python.exe",
- py34: "C:\\Python34\\python.exe",
- py35: "C:\\Python35\\python.exe",
- py36: "C:\\Python36\\python.exe",
- py37: "C:\\Python37\\python.exe"
- ]
- if (toxenv == "py35" || toxenv == "py36" || toxenv == "py37") {
- opensslPaths = [
- "windows": [
- "include": "C:\\OpenSSL-Win32-2015\\include",
- "lib": "C:\\OpenSSL-Win32-2015\\lib"
- ],
- "windows64": [
- "include": "C:\\OpenSSL-Win64-2015\\include",
- "lib": "C:\\OpenSSL-Win64-2015\\lib"
- ]
- ]
- } else {
- opensslPaths = [
- "windows": [
- "include": "C:\\OpenSSL-Win32-2010\\include",
- "lib": "C:\\OpenSSL-Win32-2010\\lib"
- ],
- "windows64": [
- "include": "C:\\OpenSSL-Win64-2010\\include",
- "lib": "C:\\OpenSSL-Win64-2010\\lib"
- ]
- ]
- }
- bat """
- cd cryptography
- @set PATH="C:\\Python27";"C:\\Python27\\Scripts";%PATH%
- @set PYTHON="${pythonPath[toxenv]}"
-
- @set INCLUDE="${opensslPaths[label]['include']}";%INCLUDE%
- @set LIB="${opensslPaths[label]['lib']}";%LIB%
- tox -r -- --wycheproof-root=../wycheproof
- IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
- virtualenv .codecov
- call .codecov/Scripts/activate
- REM this pin must be kept in sync with tox.ini
- pip install coverage
- pip install codecov
- codecov -e JOB_BASE_NAME,LABEL,TOXENV
- """
- } else if (label.contains("sierra") || label.contains("yosemite")) {
- ansiColor {
- sh """#!/usr/bin/env bash
- set -xe
- # Jenkins logs in as a non-interactive shell, so we don't even have /usr/local/bin in PATH
- export PATH="/usr/local/bin:\${PATH}"
- export PATH="/Users/jenkins/.pyenv/shims:\${PATH}"
- cd cryptography
- CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 \
- LDFLAGS="/usr/local/opt/openssl\\@1.1/lib/libcrypto.a /usr/local/opt/openssl\\@1.1/lib/libssl.a" \
- CFLAGS="-I/usr/local/opt/openssl\\@1.1/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -Wno-error=unused-command-line-argument -mmacosx-version-min=10.9" \
- tox -r -- --color=yes --wycheproof-root=../wycheproof
- virtualenv .venv
- source .venv/bin/activate
- # This pin must be kept in sync with tox.ini
- pip install coverage
- bash <(curl -s https://codecov.io/bash) -e JOB_BASE_NAME,LABEL,TOXENV
- """
- }
- } else {
- ansiColor {
- sh """#!/usr/bin/env bash
- set -xe
- cd cryptography
- tox -r -- --color=yes --wycheproof-root=../wycheproof
- virtualenv .venv
- source .venv/bin/activate
- # This pin must be kept in sync with tox.ini
- pip install coverage
- bash <(curl -s https://codecov.io/bash) -e JOB_BASE_NAME,LABEL,TOXENV,IMAGE_NAME
- """
- }
- if (artifacts) {
- archiveArtifacts artifacts: artifacts, excludes: artifactExcludes
- }
- }
- }
- }
- }
- } finally {
- deleteDir()
- }
-
-}
-
-def builders = [:]
-for (config in configs) {
- def label = config["label"]
- def toxenvs = config["toxenvs"]
- def artifacts = config["artifacts"]
- def artifactExcludes = config["artifactExcludes"]
-
- for (_toxenv in toxenvs) {
- def toxenv = _toxenv
-
- if (label.contains("docker")) {
- def imageName = config["imageName"]
- def combinedName = "${imageName}-${toxenv}"
- builders[combinedName] = {
- node(label) {
- stage(combinedName) {
- def buildImage = docker.image(imageName)
- buildImage.pull()
- buildImage.inside {
- build(toxenv, label, imageName, artifacts, artifactExcludes)
- }
- }
- }
- }
- } else {
- def combinedName = "${label}-${toxenv}"
- builders[combinedName] = {
- node(label) {
- stage(combinedName) {
- build(toxenv, label, '', null, null)
- }
- }
- }
- }
- }
-}
-
-/* Add the python setup.py test builder */
-builders["setup.py-test"] = {
- node("docker") {
- stage("python setup.py test") {
- docker.image("pyca/cryptography-runner-ubuntu-rolling").inside {
- try {
- checkout_git("docker")
- sh """#!/usr/bin/env bash
- set -xe
- cd cryptography
- virtualenv .venv
- source .venv/bin/activate
- python setup.py test
- """
- } finally {
- deleteDir()
- }
-
- }
- }
- }
-}
-
-parallel builders
diff --git a/LICENSE b/LICENSE
index a7692a9b9..07074259b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -2,282 +2,5 @@ This software is made available under the terms of *either* of the licenses
found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made
under the terms of *both* these licenses.
-The code used in the OpenSSL locking callback and OS random engine is derived
-from CPython, and is licensed under the terms of the PSF License Agreement.
-
-
-LICENSE.APACHE:
- Apache License
- Version 2.0, January 2004
- https://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-LICENSE.BSD:
-Copyright (c) Individual contributors.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of PyCA Cryptography nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-
-LICENSE.PSF:
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
- the Individual or Organization ("Licensee") accessing and otherwise using Python
- 2.7.12 software in source or binary form and its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, PSF hereby
- grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
- analyze, test, perform and/or display publicly, prepare derivative works,
- distribute, and otherwise use Python 2.7.12 alone or in any derivative
- version, provided, however, that PSF's License Agreement and PSF's notice of
- copyright, i.e., "Copyright © 2001-2016 Python Software Foundation; All Rights
- Reserved" are retained in Python 2.7.12 alone or in any derivative version
- prepared by Licensee.
-
-3. In the event Licensee prepares a derivative work that is based on or
- incorporates Python 2.7.12 or any part thereof, and wants to make the
- derivative work available to others as provided herein, then Licensee hereby
- agrees to include in any such work a brief summary of the changes made to Python
- 2.7.12.
-
-4. PSF is making Python 2.7.12 available to Licensee on an "AS IS" basis.
- PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
- EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
- USE OF PYTHON 2.7.12 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.12
- FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
- MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.12, OR ANY DERIVATIVE
- THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material breach of
- its terms and conditions.
-
-7. Nothing in this License Agreement shall be deemed to create any relationship
- of agency, partnership, or joint venture between PSF and Licensee. This License
- Agreement does not grant permission to use PSF trademarks or trade name in a
- trademark sense to endorse or promote products or services of Licensee, or any
- third party.
-
-8. By copying, installing or otherwise using Python 2.7.12, Licensee agrees
- to be bound by the terms and conditions of this License Agreement.
+The code used in the OS random engine is derived from CPython, and is licensed
+under the terms of the PSF License Agreement.
diff --git a/MANIFEST.in b/MANIFEST.in
index 373c24202..5c82725a4 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,6 +4,7 @@ include CONTRIBUTING.rst
include LICENSE
include LICENSE.APACHE
include LICENSE.BSD
+include LICENSE.PSF
include README.rst
include pyproject.toml
@@ -12,4 +13,12 @@ recursive-include docs *
recursive-include src/_cffi_src *.py *.c *.h
prune docs/_build
recursive-include tests *.py
+exclude vectors
recursive-exclude vectors *
+
+recursive-exclude .github *
+
+exclude release.py .coveragerc codecov.yml .readthedocs.yml dev-requirements.txt rtd-requirements.txt tox.ini
+
+recursive-exclude .zuul.d *
+recursive-exclude .zuul.playbooks *
diff --git a/METADATA b/METADATA
index 156c17ab9..ca6f3d54e 100644
--- a/METADATA
+++ b/METADATA
@@ -2,7 +2,7 @@ name: "cryptography"
description:
"cryptography is a package which provides cryptographic recipes and "
"primitives to Python developers. Our goal is for it to be your "
- ""cryptographic standard library". It supports Python 2.7, Python 3.4+, and "
+ ""cryptographic standard library". It supports Python 2.7, Python 3.6+, and "
"PyPy 5.4+."
third_party {
@@ -14,7 +14,7 @@ third_party {
type: GIT
value: "https://github.com/pyca/cryptography"
}
- version: "2.5"
- last_upgrade_date { year: 2019 month: 2 day: 26 }
+ version: "3.3.2"
+ last_upgrade_date { year: 2021 month: 11 day: 8 }
license_type: NOTICE
}
diff --git a/README.rst b/README.rst
index 13f2d7d11..10de198b8 100644
--- a/README.rst
+++ b/README.rst
@@ -9,8 +9,8 @@ pyca/cryptography
:target: https://cryptography.io
:alt: Latest Docs
-.. image:: https://travis-ci.org/pyca/cryptography.svg?branch=master
- :target: https://travis-ci.org/pyca/cryptography
+.. image:: https://github.com/pyca/cryptography/workflows/CI/badge.svg?branch=master
+ :target: https://github.com/pyca/cryptography/actions?query=workflow%3ACI+branch%3Amaster
.. image:: https://codecov.io/github/pyca/cryptography/coverage.svg?branch=master
:target: https://codecov.io/github/pyca/cryptography?branch=master
@@ -18,7 +18,7 @@ pyca/cryptography
``cryptography`` is a package which provides cryptographic recipes and
primitives to Python developers. Our goal is for it to be your "cryptographic
-standard library". It supports Python 2.7, Python 3.4+, and PyPy 5.3+.
+standard library". It supports Python 2.7, Python 3.6+, and PyPy 5.4+.
``cryptography`` includes both high level recipes and low level interfaces to
common cryptographic algorithms such as symmetric ciphers, message digests, and
@@ -65,7 +65,7 @@ documentation.
.. _`documentation`: https://cryptography.io/
-.. _`the installation documentation`: https://cryptography.io/en/latest/installation/
+.. _`the installation documentation`: https://cryptography.io/en/latest/installation.html
.. _`issue tracker`: https://github.com/pyca/cryptography/issues
.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev
-.. _`security reporting`: https://cryptography.io/en/latest/security/
+.. _`security reporting`: https://cryptography.io/en/latest/security.html
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 58827ed47..333faaddf 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,7 +1,5 @@
click
-clint
coverage
-requests
tox >= 2.4.1
twine >= 1.8.0
-e .[test,docs,docstest,pep8test]
diff --git a/docs/api-stability.rst b/docs/api-stability.rst
index 205b18447..fd34ced0a 100644
--- a/docs/api-stability.rst
+++ b/docs/api-stability.rst
@@ -1,7 +1,7 @@
API stability
=============
-From its first release, ``cryptography`` will have a strong API stability
+From its first release, ``cryptography`` has had a strong API stability
policy.
What does this policy cover?
diff --git a/docs/conf.py b/docs/conf.py
index 4349b0587..fb67adabc 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -35,7 +35,7 @@ except ImportError:
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.insert(0, os.path.abspath('.'))
+sys.path.insert(0, os.path.abspath("."))
# -- General configuration ----------------------------------------------------
@@ -45,33 +45,33 @@ sys.path.insert(0, os.path.abspath('.'))
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
- 'sphinx.ext.autodoc',
- 'sphinx.ext.doctest',
- 'sphinx.ext.intersphinx',
- 'sphinx.ext.viewcode',
- 'cryptography-docs',
+ "sphinx.ext.autodoc",
+ "sphinx.ext.doctest",
+ "sphinx.ext.intersphinx",
+ "sphinx.ext.viewcode",
+ "cryptography-docs",
]
if spelling is not None:
- extensions.append('sphinxcontrib.spelling')
+ extensions.append("sphinxcontrib.spelling")
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
nitpicky = True
# The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = ".rst"
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
# General information about the project.
-project = 'Cryptography'
-copyright = '2013-2017, Individual Contributors'
+project = "Cryptography"
+copyright = "2013-2021, Individual Contributors"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -81,7 +81,7 @@ copyright = '2013-2017, Individual Contributors'
base_dir = os.path.join(os.path.dirname(__file__), os.pardir)
about = {}
with open(os.path.join(base_dir, "src", "cryptography", "__about__.py")) as f:
- exec(f.read(), about)
+ exec (f.read(), about)
version = release = about["__version__"]
@@ -97,7 +97,7 @@ version = release = about["__version__"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ["_build"]
# The reST default role (used for this markup: `text`) to use for all documents
# default_role = None
@@ -114,7 +114,7 @@ exclude_patterns = ['_build']
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
# -- Options for HTML output --------------------------------------------------
@@ -130,22 +130,26 @@ else:
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
# Output file base name for HTML help builder.
-htmlhelp_basename = 'Cryptographydoc'
+htmlhelp_basename = "Cryptographydoc"
# -- Options for LaTeX output -------------------------------------------------
-latex_elements = {
-}
+latex_elements = {}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual])
latex_documents = [
- ('index', 'Cryptography.tex', 'Cryptography Documentation',
- 'Individual Contributors', 'manual'),
+ (
+ "index",
+ "Cryptography.tex",
+ "Cryptography Documentation",
+ "Individual Contributors",
+ "manual",
+ ),
]
# -- Options for manual page output -------------------------------------------
@@ -153,8 +157,13 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
- ('index', 'cryptography', 'Cryptography Documentation',
- ['Individual Contributors'], 1)
+ (
+ "index",
+ "cryptography",
+ "Cryptography Documentation",
+ ["Individual Contributors"],
+ 1,
+ )
]
# -- Options for Texinfo output -----------------------------------------------
@@ -163,22 +172,31 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- ('index', 'Cryptography', 'Cryptography Documentation',
- 'Individual Contributors', 'Cryptography',
- 'One line description of project.',
- 'Miscellaneous'),
+ (
+ "index",
+ "Cryptography",
+ "Cryptography Documentation",
+ "Individual Contributors",
+ "Cryptography",
+ "One line description of project.",
+ "Miscellaneous",
+ ),
]
# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'https://docs.python.org/3': None}
+intersphinx_mapping = {"https://docs.python.org/3": None}
-epub_theme = 'epub'
+epub_theme = "epub"
# Retry requests in the linkcheck builder so that we're resillient against
# transient network errors.
linkcheck_retries = 10
+linkcheck_timeout = 5
+
linkcheck_ignore = [
# Small DH key results in a TLS failure on modern OpenSSL
- "https://info.isl.ntt.co.jp/crypt/eng/camellia/",
+ r"https://info.isl.ntt.co.jp/crypt/eng/camellia/",
+ # Inconsistent small DH params they seem incapable of fixing
+ r"https://www.secg.org/sec1-v2.pdf",
]
diff --git a/docs/development/c-bindings.rst b/docs/development/c-bindings.rst
index 1b58dab62..e53e0bae7 100644
--- a/docs/development/c-bindings.rst
+++ b/docs/development/c-bindings.rst
@@ -5,7 +5,7 @@ C bindings are bindings to C libraries, using cffi_ whenever possible.
.. _cffi: https://cffi.readthedocs.io
-Bindings live in :py:mod:`cryptography.hazmat.bindings`.
+Bindings live in ``cryptography.hazmat.bindings``.
When modifying the bindings you will need to recompile the C extensions to
test the changes. This can be accomplished with ``pip install -e .`` in the
@@ -189,9 +189,9 @@ Caveats
Sometimes, a set of loosely related features are added in the same
version, and it's impractical to create ``#ifdef`` statements for each
one. In that case, it may make sense to either check for a particular
-version. For example, to check for OpenSSL 1.1.0 or newer::
+version. For example, to check for OpenSSL 1.1.1 or newer::
- #if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+ #if CRYPTOGRAPHY_OPENSSL_111_OR_GREATER
Sometimes, the version of a library on a particular platform will have
features that you thought it wouldn't, based on its version.
diff --git a/docs/development/custom-vectors/arc4/generate_arc4.py b/docs/development/custom-vectors/arc4/generate_arc4.py
index 3dee44a30..2ca85c98d 100644
--- a/docs/development/custom-vectors/arc4/generate_arc4.py
+++ b/docs/development/custom-vectors/arc4/generate_arc4.py
@@ -12,10 +12,14 @@ from cryptography.hazmat.primitives.ciphers import algorithms
_RFC6229_KEY_MATERIALS = [
- (True,
- 8 * '0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20'),
- (False,
- 8 * '1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a')
+ (
+ True,
+ 8 * "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20",
+ ),
+ (
+ False,
+ 8 * "1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a",
+ ),
]
@@ -37,42 +41,43 @@ _RFC6229_OFFSETS = [
3056,
3072,
4080,
- 4096
+ 4096,
]
-_SIZES_TO_GENERATE = [
- 160
-]
+_SIZES_TO_GENERATE = [160]
def _key_for_size(size, keyinfo):
msb, key = keyinfo
if msb:
- return key[:size // 4]
+ return key[: size // 4]
else:
- return key[-size // 4:]
+ return key[-size // 4 :]
def _build_vectors():
count = 0
output = []
key = None
- plaintext = binascii.unhexlify(32 * '0')
+ plaintext = binascii.unhexlify(32 * "0")
for size in _SIZES_TO_GENERATE:
for keyinfo in _RFC6229_KEY_MATERIALS:
key = _key_for_size(size, keyinfo)
cipher = ciphers.Cipher(
algorithms.ARC4(binascii.unhexlify(key)),
None,
- default_backend())
+ default_backend(),
+ )
encryptor = cipher.encryptor()
current_offset = 0
for offset in _RFC6229_OFFSETS:
if offset % 16 != 0:
raise ValueError(
- "Offset {} is not evenly divisible by 16"
- .format(offset))
+ "Offset {} is not evenly divisible by 16".format(
+ offset
+ )
+ )
while current_offset < offset:
encryptor.update(plaintext)
current_offset += len(plaintext)
@@ -80,19 +85,23 @@ def _build_vectors():
count += 1
output.append("KEY = {}".format(key))
output.append("OFFSET = {}".format(offset))
- output.append("PLAINTEXT = {}".format(
- binascii.hexlify(plaintext)))
- output.append("CIPHERTEXT = {}".format(
- binascii.hexlify(encryptor.update(plaintext))))
+ output.append(
+ "PLAINTEXT = {}".format(binascii.hexlify(plaintext))
+ )
+ output.append(
+ "CIPHERTEXT = {}".format(
+ binascii.hexlify(encryptor.update(plaintext))
+ )
+ )
current_offset += len(plaintext)
assert not encryptor.finalize()
return "\n".join(output)
def _write_file(data, filename):
- with open(filename, 'w') as f:
+ with open(filename, "w") as f:
f.write(data)
-if __name__ == '__main__':
- _write_file(_build_vectors(), 'arc4.txt')
+if __name__ == "__main__":
+ _write_file(_build_vectors(), "arc4.txt")
diff --git a/docs/development/custom-vectors/cast5/generate_cast5.py b/docs/development/custom-vectors/cast5/generate_cast5.py
index a0e28e36e..5208b90d8 100644
--- a/docs/development/custom-vectors/cast5/generate_cast5.py
+++ b/docs/development/custom-vectors/cast5/generate_cast5.py
@@ -14,7 +14,7 @@ def encrypt(mode, key, iv, plaintext):
cipher = base.Cipher(
algorithms.CAST5(binascii.unhexlify(key)),
mode(binascii.unhexlify(iv)),
- default_backend()
+ default_backend(),
)
encryptor = cipher.encryptor()
ct = encryptor.update(binascii.unhexlify(plaintext))
@@ -23,33 +23,36 @@ def encrypt(mode, key, iv, plaintext):
def build_vectors(mode, filename):
- vector_file = open(filename, "r")
-
count = 0
output = []
key = None
iv = None
plaintext = None
- for line in vector_file:
- line = line.strip()
- if line.startswith("KEY"):
- if count != 0:
- output.append("CIPHERTEXT = {}".format(
- encrypt(mode, key, iv, plaintext))
- )
- output.append("\nCOUNT = {}".format(count))
- count += 1
- name, key = line.split(" = ")
- output.append("KEY = {}".format(key))
- elif line.startswith("IV"):
- name, iv = line.split(" = ")
- iv = iv[0:16]
- output.append("IV = {}".format(iv))
- elif line.startswith("PLAINTEXT"):
- name, plaintext = line.split(" = ")
- output.append("PLAINTEXT = {}".format(plaintext))
- output.append("CIPHERTEXT = {}".format(encrypt(mode, key, iv, plaintext)))
+ with open(filename, "r") as vector_file:
+ for line in vector_file:
+ line = line.strip()
+ if line.startswith("KEY"):
+ if count != 0:
+ output.append(
+ "CIPHERTEXT = {}".format(
+ encrypt(mode, key, iv, plaintext)
+ )
+ )
+ output.append("\nCOUNT = {}".format(count))
+ count += 1
+ name, key = line.split(" = ")
+ output.append("KEY = {}".format(key))
+ elif line.startswith("IV"):
+ name, iv = line.split(" = ")
+ iv = iv[0:16]
+ output.append("IV = {}".format(iv))
+ elif line.startswith("PLAINTEXT"):
+ name, plaintext = line.split(" = ")
+ output.append("PLAINTEXT = {}".format(plaintext))
+ output.append(
+ "CIPHERTEXT = {}".format(encrypt(mode, key, iv, plaintext))
+ )
return "\n".join(output)
diff --git a/docs/development/custom-vectors/hkdf/generate_hkdf.py b/docs/development/custom-vectors/hkdf/generate_hkdf.py
index 767aedd83..aa2fc274f 100644
--- a/docs/development/custom-vectors/hkdf/generate_hkdf.py
+++ b/docs/development/custom-vectors/hkdf/generate_hkdf.py
@@ -13,27 +13,31 @@ from cryptography.hazmat.primitives.kdf.hkdf import HKDF
IKM = binascii.unhexlify(b"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
L = 1200
OKM = HKDF(
- algorithm=hashes.SHA256(), length=L, salt=None, info=None,
- backend=default_backend()
+ algorithm=hashes.SHA256(),
+ length=L,
+ salt=None,
+ info=None,
+ backend=default_backend(),
).derive(IKM)
def _build_vectors():
- output = []
- output.append("COUNT = 0")
- output.append("Hash = SHA-256")
- output.append("IKM = " + binascii.hexlify(IKM).decode("ascii"))
- output.append("salt = ")
- output.append("info = ")
- output.append("L = {}".format(L))
- output.append("OKM = " + binascii.hexlify(OKM).decode("ascii"))
+ output = [
+ "COUNT = 0",
+ "Hash = SHA-256",
+ "IKM = " + binascii.hexlify(IKM).decode("ascii"),
+ "salt = ",
+ "info = ",
+ "L = {}".format(L),
+ "OKM = " + binascii.hexlify(OKM).decode("ascii"),
+ ]
return "\n".join(output)
def _write_file(data, filename):
- with open(filename, 'w') as f:
+ with open(filename, "w") as f:
f.write(data)
-if __name__ == '__main__':
- _write_file(_build_vectors(), 'hkdf.txt')
+if __name__ == "__main__":
+ _write_file(_build_vectors(), "hkdf.txt")
diff --git a/docs/development/custom-vectors/idea/generate_idea.py b/docs/development/custom-vectors/idea/generate_idea.py
index 2eb6996ef..00309567b 100644
--- a/docs/development/custom-vectors/idea/generate_idea.py
+++ b/docs/development/custom-vectors/idea/generate_idea.py
@@ -8,7 +8,7 @@ def encrypt(mode, key, iv, plaintext):
cipher = base.Cipher(
algorithms.IDEA(binascii.unhexlify(key)),
mode(binascii.unhexlify(iv)),
- backend
+ backend,
)
encryptor = cipher.encryptor()
ct = encryptor.update(binascii.unhexlify(plaintext))
@@ -29,8 +29,10 @@ def build_vectors(mode, filename):
line = line.strip()
if line.startswith("KEY"):
if count != 0:
- output.append("CIPHERTEXT = {0}".format(
- encrypt(mode, key, iv, plaintext))
+ output.append(
+ "CIPHERTEXT = {0}".format(
+ encrypt(mode, key, iv, plaintext)
+ )
)
output.append("\nCOUNT = {0}".format(count))
count += 1
diff --git a/docs/development/custom-vectors/idea/verify_idea.py b/docs/development/custom-vectors/idea/verify_idea.py
index 89713c801..d356de0ba 100644
--- a/docs/development/custom-vectors/idea/verify_idea.py
+++ b/docs/development/custom-vectors/idea/verify_idea.py
@@ -8,11 +8,13 @@ BLOCK_SIZE = 64
def encrypt(mode, key, iv, plaintext):
- encryptor = botan.Cipher("IDEA/{0}/NoPadding".format(mode), "encrypt",
- binascii.unhexlify(key))
+ encryptor = botan.Cipher(
+ "IDEA/{0}/NoPadding".format(mode), "encrypt", binascii.unhexlify(key)
+ )
- cipher_text = encryptor.cipher(binascii.unhexlify(plaintext),
- binascii.unhexlify(iv))
+ cipher_text = encryptor.cipher(
+ binascii.unhexlify(plaintext), binascii.unhexlify(iv)
+ )
return binascii.hexlify(cipher_text)
@@ -22,12 +24,7 @@ def verify_vectors(mode, filename):
vectors = load_nist_vectors(vector_file)
for vector in vectors:
- ct = encrypt(
- mode,
- vector["key"],
- vector["iv"],
- vector["plaintext"]
- )
+ ct = encrypt(mode, vector["key"], vector["iv"], vector["plaintext"])
assert ct == vector["ciphertext"]
diff --git a/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py
index bd5148f54..a43e1506d 100644
--- a/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py
+++ b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py
@@ -62,9 +62,8 @@ def build_vectors(mgf1alg, hashalg, filename):
dmq1=private["dmq1"],
iqmp=private["iqmp"],
public_numbers=rsa.RSAPublicNumbers(
- e=private["public_exponent"],
- n=private["modulus"]
- )
+ e=private["public_exponent"], n=private["modulus"]
+ ),
).private_key(backend)
count = 1
@@ -74,8 +73,8 @@ def build_vectors(mgf1alg, hashalg, filename):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
- )
+ label=None,
+ ),
)
assert message == binascii.unhexlify(example["message"])
ct = pkey.encrypt(
@@ -83,8 +82,8 @@ def build_vectors(mgf1alg, hashalg, filename):
padding.OAEP(
mgf=padding.MGF1(algorithm=mgf1alg),
algorithm=hashalg,
- label=None
- )
+ label=None,
+ ),
)
output.append(
b"# OAEP Example {0} alg={1} mgf1={2}".format(
@@ -116,13 +115,12 @@ hashalgs = [
hashes.SHA512(),
]
for hashtuple in itertools.product(hashalgs, hashalgs):
- if (
- isinstance(hashtuple[0], hashes.SHA1) and
- isinstance(hashtuple[1], hashes.SHA1)
+ if isinstance(hashtuple[0], hashes.SHA1) and isinstance(
+ hashtuple[1], hashes.SHA1
):
continue
write_file(
build_vectors(hashtuple[0], hashtuple[1], oaep_path),
- "oaep-{0}-{1}.txt".format(hashtuple[0].name, hashtuple[1].name)
+ "oaep-{0}-{1}.txt".format(hashtuple[0].name, hashtuple[1].name),
)
diff --git a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py
index d6a2071ac..bfb150ba6 100644
--- a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py
+++ b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py
@@ -10,9 +10,7 @@ from ecdsa.util import sigdecode_der, sigencode_der
from cryptography_vectors import open_vector_file
-from tests.utils import (
- load_fips_ecdsa_signing_vectors, load_vectors_from_file
-)
+from tests.utils import load_fips_ecdsa_signing_vectors, load_vectors_from_file
HASHLIB_HASH_TYPES = {
"SHA-1": hashlib.sha1,
@@ -32,13 +30,13 @@ class TruncatedHash(object):
return self
def digest(self):
- return self.hasher.digest()[:256 // 8]
+ return self.hasher.digest()[: 256 // 8]
def build_vectors(fips_vectors):
vectors = defaultdict(list)
for vector in fips_vectors:
- vectors[vector['digest_algorithm']].append(vector['message'])
+ vectors[vector["digest_algorithm"]].append(vector["message"])
for digest_algorithm, messages in vectors.items():
if digest_algorithm not in HASHLIB_HASH_TYPES:
@@ -55,8 +53,9 @@ def build_vectors(fips_vectors):
# Sign the message using warner/ecdsa
secret_key = SigningKey.generate(curve=SECP256k1)
public_key = secret_key.get_verifying_key()
- signature = secret_key.sign(message, hashfunc=hash_func,
- sigencode=sigencode_der)
+ signature = secret_key.sign(
+ message, hashfunc=hash_func, sigencode=sigencode_der
+ )
r, s = sigdecode_der(signature, None)
@@ -79,12 +78,8 @@ source_path = os.path.join("asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt")
dest_path = os.path.join("asymmetric", "ECDSA", "SECP256K1", "SigGen.txt")
fips_vectors = load_vectors_from_file(
- source_path,
- load_fips_ecdsa_signing_vectors
+ source_path, load_fips_ecdsa_signing_vectors
)
with open_vector_file(dest_path, "w") as dest_file:
- write_file(
- build_vectors(fips_vectors),
- dest_file
- )
+ write_file(build_vectors(fips_vectors), dest_file)
diff --git a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py
index b236d77fc..f721b0001 100644
--- a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py
+++ b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py
@@ -6,12 +6,10 @@ from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import (
- encode_dss_signature
+ encode_dss_signature,
)
-from tests.utils import (
- load_fips_ecdsa_signing_vectors, load_vectors_from_file
-)
+from tests.utils import load_fips_ecdsa_signing_vectors, load_vectors_from_file
CRYPTOGRAPHY_HASH_TYPES = {
"SHA-1": hashes.SHA1,
@@ -23,37 +21,32 @@ CRYPTOGRAPHY_HASH_TYPES = {
def verify_one_vector(vector):
- digest_algorithm = vector['digest_algorithm']
- message = vector['message']
- x = vector['x']
- y = vector['y']
- signature = encode_dss_signature(vector['r'], vector['s'])
-
- numbers = ec.EllipticCurvePublicNumbers(
- x, y,
- ec.SECP256K1()
- )
+ digest_algorithm = vector["digest_algorithm"]
+ message = vector["message"]
+ x = vector["x"]
+ y = vector["y"]
+ signature = encode_dss_signature(vector["r"], vector["s"])
+
+ numbers = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256K1())
key = numbers.public_key(default_backend())
verifier = key.verifier(
- signature,
- ec.ECDSA(CRYPTOGRAPHY_HASH_TYPES[digest_algorithm]())
+ signature, ec.ECDSA(CRYPTOGRAPHY_HASH_TYPES[digest_algorithm]())
)
verifier.update(message)
- return verifier.verify()
+ verifier.verify()
def verify_vectors(vectors):
for vector in vectors:
- assert verify_one_vector(vector)
+ verify_one_vector(vector)
vector_path = os.path.join("asymmetric", "ECDSA", "SECP256K1", "SigGen.txt")
secp256k1_vectors = load_vectors_from_file(
- vector_path,
- load_fips_ecdsa_signing_vectors
+ vector_path, load_fips_ecdsa_signing_vectors
)
verify_vectors(secp256k1_vectors)
diff --git a/docs/development/custom-vectors/seed/generate_seed.py b/docs/development/custom-vectors/seed/generate_seed.py
index 5c62d6713..046fcfb87 100644
--- a/docs/development/custom-vectors/seed/generate_seed.py
+++ b/docs/development/custom-vectors/seed/generate_seed.py
@@ -8,7 +8,7 @@ def encrypt(mode, key, iv, plaintext):
cipher = base.Cipher(
algorithms.SEED(binascii.unhexlify(key)),
mode(binascii.unhexlify(iv)),
- backend
+ backend,
)
encryptor = cipher.encryptor()
ct = encryptor.update(binascii.unhexlify(plaintext))
@@ -29,8 +29,10 @@ def build_vectors(mode, filename):
line = line.strip()
if line.startswith("KEY"):
if count != 0:
- output.append("CIPHERTEXT = {0}".format(
- encrypt(mode, key, iv, plaintext))
+ output.append(
+ "CIPHERTEXT = {0}".format(
+ encrypt(mode, key, iv, plaintext)
+ )
)
output.append("\nCOUNT = {0}".format(count))
count += 1
diff --git a/docs/development/custom-vectors/seed/verify_seed.py b/docs/development/custom-vectors/seed/verify_seed.py
index e626428cb..252088d08 100644
--- a/docs/development/custom-vectors/seed/verify_seed.py
+++ b/docs/development/custom-vectors/seed/verify_seed.py
@@ -6,11 +6,13 @@ from tests.utils import load_nist_vectors
def encrypt(mode, key, iv, plaintext):
- encryptor = botan.Cipher("SEED/{0}/NoPadding".format(mode), "encrypt",
- binascii.unhexlify(key))
+ encryptor = botan.Cipher(
+ "SEED/{0}/NoPadding".format(mode), "encrypt", binascii.unhexlify(key)
+ )
- cipher_text = encryptor.cipher(binascii.unhexlify(plaintext),
- binascii.unhexlify(iv))
+ cipher_text = encryptor.cipher(
+ binascii.unhexlify(plaintext), binascii.unhexlify(iv)
+ )
return binascii.hexlify(cipher_text)
@@ -20,12 +22,7 @@ def verify_vectors(mode, filename):
vectors = load_nist_vectors(vector_file)
for vector in vectors:
- ct = encrypt(
- mode,
- vector["key"],
- vector["iv"],
- vector["plaintext"]
- )
+ ct = encrypt(mode, vector["key"], vector["iv"], vector["plaintext"])
assert ct == vector["ciphertext"]
diff --git a/docs/development/getting-started.rst b/docs/development/getting-started.rst
index cc333e4d3..1d939a9c3 100644
--- a/docs/development/getting-started.rst
+++ b/docs/development/getting-started.rst
@@ -81,7 +81,7 @@ each supported Python version and run the tests. For example:
...
py27: commands succeeded
ERROR: pypy: InterpreterNotFound: pypy
- py34: commands succeeded
+ py38: commands succeeded
docs: commands succeeded
pep8: commands succeeded
diff --git a/docs/development/reviewing-patches.rst b/docs/development/reviewing-patches.rst
index bd3ee96ac..084461830 100644
--- a/docs/development/reviewing-patches.rst
+++ b/docs/development/reviewing-patches.rst
@@ -7,18 +7,18 @@ review is our opportunity to share knowledge, design ideas and make friends.
When reviewing a patch try to keep each of these concepts in mind:
-Architecture
-------------
-
-* Is the proposed change being made in the correct place? Is it a fix in a
- backend when it should be in the primitives?
-
Intent
------
* What is the change being proposed?
* Do we want this feature or is the bug they're fixing really a bug?
+Architecture
+------------
+
+* Is the proposed change being made in the correct place? Is it a fix in a
+ backend when it should be in the primitives?
+
Implementation
--------------
diff --git a/docs/development/submitting-patches.rst b/docs/development/submitting-patches.rst
index ec00aa528..b4ed175e6 100644
--- a/docs/development/submitting-patches.rst
+++ b/docs/development/submitting-patches.rst
@@ -19,9 +19,10 @@ Code
----
When in doubt, refer to :pep:`8` for Python code. You can check if your code
-meets our automated requirements by running ``flake8`` against it. If you've
-installed the development requirements this will automatically use our
-configuration. You can also run the ``tox`` job with ``tox -e pep8``.
+meets our automated requirements by formatting it with ``black`` and running
+``flake8`` against it. If you've installed the development requirements this
+will automatically use our configuration. You can also run the ``tox`` job with
+``tox -e pep8``.
`Write comments as complete sentences.`_
@@ -80,10 +81,9 @@ Every recipe should include a version or algorithmic marker of some sort in its
output in order to allow transparent upgrading of the algorithms in use, as
the algorithms or parameters needed to achieve a given security margin evolve.
-APIs at the :doc:`/hazmat/primitives/index` layer should always take an
-explicit backend, APIs at the recipes layer should automatically use the
-:func:`~cryptography.hazmat.backends.default_backend`, but optionally allow
-specifying a different backend.
+APIs at the :doc:`/hazmat/primitives/index` and recipes layer should
+automatically use the :func:`~cryptography.hazmat.backends.default_backend`,
+but optionally allow specifying a different backend.
C bindings
~~~~~~~~~~
@@ -156,6 +156,6 @@ So, specifically:
.. _`Write comments as complete sentences.`: https://nedbatchelder.com/blog/201401/comments_should_be_sentences.html
.. _`syntax`: https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#info-field-lists
-.. _`Studies have shown`: https://smartbear.com/SmartBear/media/pdfs/11_Best_Practices_for_Peer_Code_Review.pdf
+.. _`Studies have shown`: https://smartbear.com/learn/code-review/best-practices-for-peer-code-review/
.. _`our mailing list`: https://mail.python.org/mailman/listinfo/cryptography-dev
.. _`doc8`: https://github.com/openstack/doc8
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index df1ecfa20..f952337e2 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -23,7 +23,7 @@ for various cryptographic algorithms. These are not included in the repository
continuous integration environments.
We have ensured all test vectors are used as of commit
-``c313761979d74b0417230eddd0f87d0cfab2b46b``.
+``2196000605e45d91097147c9c71f26b72af58003``.
Asymmetric ciphers
~~~~~~~~~~~~~~~~~~
@@ -78,6 +78,8 @@ Custom asymmetric vectors
* ``asymmetric/PEM_Serialization/rsa_public_key.pem`` and
``asymmetric/DER_Serialization/rsa_public_key.der``- Contains an RSA 2048
bit public generated using OpenSSL from ``rsa_private_key.pem``.
+* ``asymmetric/PEM_Serialization/dsa_4096.pem`` - Contains a 4096-bit DSA
+ private key generated using OpenSSL.
* ``asymmetric/PEM_Serialization/dsaparam.pem`` - Contains 2048-bit DSA
parameters generated using OpenSSL; contains no keys.
* ``asymmetric/PEM_Serialization/dsa_private_key.pem`` - Contains a DSA 2048
@@ -86,6 +88,11 @@ Custom asymmetric vectors
* ``asymmetric/PEM_Serialization/dsa_public_key.pem`` and
``asymmetric/DER_Serialization/dsa_public_key.der`` - Contains a DSA 2048 bit
key generated using OpenSSL from ``dsa_private_key.pem``.
+* ``asymmetric/DER_Serialization/dsa_public_key_no_params.der`` - Contains a
+ DSA public key with the optional parameters removed.
+* ``asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.der`` -
+ Contains a DSA public key with the bit string padding value set to 2 rather
+ than the required 0.
* ``asymmetric/PKCS8/unenc-dsa-pkcs8.pem`` and
``asymmetric/DER_Serialization/unenc-dsa-pkcs8.der`` - Contains a DSA 1024
bit key generated using OpenSSL.
@@ -102,6 +109,8 @@ Custom asymmetric vectors
* ``x509/custom/ca/ca_key.pem`` - An unencrypted PCKS8 ``secp256r1`` key. It is
the private key for the certificate ``x509/custom/ca/ca.pem``. This key is
encoded in several of the PKCS12 custom vectors.
+* ``x509/custom/ca/rsa_key.pem`` - An unencrypted PCKS8 4096 bit RSA key. It is
+ the private key for the certificate ``x509/custom/ca/rsa_ca.pem``.
* ``asymmetric/EC/compressed_points.txt`` - Contains compressed public points
generated using OpenSSL.
* ``asymmetric/X448/x448-pkcs8-enc.pem`` and
@@ -111,6 +120,13 @@ Custom asymmetric vectors
contain an unencrypted X448 key.
* ``asymmetric/X448/x448-pub.pem`` and ``asymmetric/X448/x448-pub.der`` contain
an X448 public key.
+* ``asymmetric/Ed25519/ed25519-pkcs8-enc.pem`` and
+ ``asymmetric/Ed25519/ed25519-pkcs8-enc.der`` contain an Ed25519 key encrypted
+ with AES 256 CBC with the password ``password``.
+* ``asymmetric/Ed25519/ed25519-pkcs8.pem`` and
+ ``asymmetric/Ed25519/ed25519-pkcs8.der`` contain an unencrypted Ed25519 key.
+* ``asymmetric/Ed25519/ed25519-pub.pem`` and
+ ``asymmetric/Ed25519/ed25519-pub.der`` contain an Ed25519 public key.
* ``asymmetric/X25519/x25519-pkcs8-enc.pem`` and
``asymmetric/X25519/x25519-pkcs8-enc.der`` contain an X25519 key encrypted
with AES 256 CBC with the password ``password``.
@@ -118,6 +134,13 @@ Custom asymmetric vectors
``asymmetric/X25519/x25519-pkcs8.der`` contain an unencrypted X25519 key.
* ``asymmetric/X25519/x25519-pub.pem`` and ``asymmetric/X25519/x25519-pub.der``
contain an X25519 public key.
+* ``asymmetric/Ed448/ed448-pkcs8-enc.pem`` and
+ ``asymmetric/Ed448/ed448-pkcs8-enc.der`` contain an Ed448 key encrypted
+ with AES 256 CBC with the password ``password``.
+* ``asymmetric/Ed448/ed448-pkcs8.pem`` and
+ ``asymmetric/Ed448/ed448-pkcs8.der`` contain an unencrypted Ed448 key.
+* ``asymmetric/Ed448/ed448-pub.pem`` and ``asymmetric/Ed448/ed448-pub.der``
+ contain an Ed448 public key.
Key exchange
@@ -161,6 +184,8 @@ Key exchange
``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.der`` and
``vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.der`` contains
are the above parameters and keys in DER format.
+* ``vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem`` contains
+ a PEM PKCS8 encoded DH key with a 256-bit key size.
* ``vectors/cryptoraphy_vectors/asymmetric/ECDH/brainpool.txt`` contains
Brainpool vectors from :rfc:`7027`.
@@ -217,6 +242,17 @@ X.509
UTCTime in its validity->not_after.
* ``letsencryptx3.pem`` - A subordinate certificate used by Let's Encrypt to
issue end entity certificates.
+* ``ed25519-rfc8410.pem`` - A certificate containing an X25519 public key with
+ an ``ed25519`` signature taken from :rfc:`8410`.
+* ``root-ed25519.pem`` - An ``ed25519`` root certificate (``ed25519`` signature
+ with ``ed25519`` public key) from the OpenSSL test suite.
+ (`root-ed25519.pem`_)
+* ``server-ed25519-cert.pem`` - An ``ed25519`` server certificate (RSA
+ signature with ``ed25519`` public key) from the OpenSSL test suite.
+ (`server-ed25519-cert.pem`_)
+* ``server-ed448-cert.pem`` - An ``ed448`` server certificate (RSA
+ signature with ``ed448`` public key) from the OpenSSL test suite.
+ (`server-ed448-cert.pem`_)
Custom X.509 Vectors
~~~~~~~~~~~~~~~~~~~~
@@ -371,9 +407,19 @@ Custom X.509 Vectors
a ``policyConstraints`` extension with a ``requireExplicitPolicy`` value.
* ``freshestcrl.pem`` - A self-signed certificate containing a ``freshestCRL``
extension.
+* ``sia.pem`` - An RSA 2048 bit self-signed certificate containing a subject
+ information access extension with both a CA repository entry and a custom
+ OID entry.
* ``ca/ca.pem`` - A self-signed certificate with ``basicConstraints`` set to
true. Its private key is ``ca/ca_key.pem``. This certificate is encoded in
several of the PKCS12 custom vectors.
+* ``negative_serial.pem`` - A certificate with a serial number that is a
+ negative number.
+* ``rsa_pss.pem`` - A certificate with an RSA PSS signature.
+* ``root-ed448.pem`` - An ``ed448`` self-signed CA certificate
+ using ``ed448-pkcs8.pem`` as key.
+* ``ca/rsa_ca.pem`` - A self-signed RSA certificate with ``basicConstraints``
+ set to true. Its private key is ``ca/rsa_key.pem``.
Custom X.509 Request Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -406,6 +452,14 @@ Custom X.509 Request Vectors
critical.
* ``invalid_signature.pem`` - A certificate signing request for an RSA
1024 bit key containing an invalid signature with correct padding.
+* ``challenge.pem`` - A certificate signing request for an RSA 2048 bit key
+ containing a challenge password.
+* ``challenge-invalid.der`` - A certificate signing request for an RSA 2048 bit
+ key containing a challenge password attribute that has been encoded as an
+ ASN.1 integer rather than a string.
+* ``challenge-unstructured.pem`` - A certificate signing request for an RSA
+ 2048 bit key containing a challenge password attribute and an unstructured
+ name attribute.
Custom X.509 Certificate Revocation List Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -480,6 +534,12 @@ X.509 OCSP Test Vectors
contains a revoked certificate and no ``nextUpdate`` value.
* ``x509/ocsp/resp-invalid-signature-oid.der`` - An OCSP response that was
modified to contain an MD2 signature algorithm object identifier.
+* ``x509/ocsp/resp-single-extension-reason.der`` - An OCSP response that
+ contains a ``CRLReason`` single extension.
+* ``x509/ocsp/resp-sct-extension.der`` - An OCSP response containing a
+ ``CT Certificate SCTs`` single extension, from the SwissSign OCSP responder.
+* ``x509/ocsp/ocsp-army.deps.mil-resp.der`` - An OCSP response containing
+ multiple ``SINGLERESP`` values.
Custom X.509 OCSP Test Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -515,6 +575,49 @@ Custom PKCS12 Test Vectors
(``x509/custom/ca/ca.pem``) encrypted via AES 256 CBC with the
password ``cryptography`` and no private key.
+Custom PKCS7 Test Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~~
+* ``pkcs7/isrg.pem`` - A PEM encoded PKCS7 file containing the ISRG X1 root
+ CA.
+* ``pkcs7/amazon-roots.p7b`` - A DER encoded PCKS7 file containing Amazon Root
+ CA 2 and 3.
+* ``pkcs7/enveloped.pem`` - A PEM encoded PKCS7 file with enveloped data.
+
+Custom OpenSSH Test Vectors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Generated by
+``asymmetric/OpenSSH/gen.sh``
+using command-line tools from OpenSSH_7.6p1 package.
+
+* ``dsa-nopsw.key``, ``dsa-nopsw.key.pub``, ``dsa-nopsw.key-cert.pub`` -
+ DSA-1024 private key; and corresponding public key in plain format
+ and with self-signed certificate.
+* ``dsa-psw.key``, ``dsa-psw.key.pub`` -
+ Password-protected DSA-1024 private key and corresponding public key.
+ Password is "password".
+* ``ecdsa-nopsw.key``, ``ecdsa-nopsw.key.pub``,
+ ``ecdsa-nopsw.key-cert.pub`` -
+ SECP256R1 private key; and corresponding public key in plain format
+ and with self-signed certificate.
+* ``ecdsa-psw.key``, ``ecdsa-psw.key.pub`` -
+ Password-protected SECP384R1 private key and corresponding public key.
+ Password is "password".
+* ``ed25519-nopsw.key``, ``ed25519-nopsw.key.pub``,
+ ``ed25519-nopsw.key-cert.pub`` -
+ Ed25519 private key; and corresponding public key in plain format
+ and with self-signed certificate.
+* ``ed25519-psw.key``, ``ed25519-psw.key.pub`` -
+ Password-protected Ed25519 private key and corresponding public key.
+ Password is "password".
+* ``rsa-nopsw.key``, ``rsa-nopsw.key.pub``,
+ ``rsa-nopsw.key-cert.pub`` -
+ RSA-2048 private key; and corresponding public key in plain format
+ and with self-signed certificate.
+* ``rsa-psw.key``, ``rsa-psw.key.pub`` -
+ Password-protected RSA-2048 private key and corresponding public key.
+ Password is "password".
+
Hashes
~~~~~~
@@ -593,6 +696,11 @@ CMAC
* AES-128, AES-192, AES-256, 3DES from `NIST SP-800-38B`_
+Poly1305
+~~~~~~~~
+
+* Test vectors from :rfc:`7539`.
+
Creating test vectors
---------------------
@@ -629,7 +737,7 @@ header format (substituting the correct information):
.. _`IETF`: https://www.ietf.org/
.. _`Project Wycheproof`: https://github.com/google/wycheproof
.. _`NIST CAVP`: https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program
-.. _`Bruce Schneier's vectors`: https://www.schneier.com/code/vectors.txt
+.. _`Bruce Schneier's vectors`: https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
.. _`Camellia page`: https://info.isl.ntt.co.jp/crypt/eng/camellia/
.. _`CRYPTREC`: https://www.cryptrec.go.jp
.. _`OpenSSL's test vectors`: https://github.com/openssl/openssl/blob/97cf1f6c2854a3a955fd7dd3a1f113deba00c9ef/crypto/evp/evptests.txt#L232
@@ -654,13 +762,16 @@ header format (substituting the correct information):
.. _`NIST SP-800-38B`: https://csrc.nist.gov/publications/detail/sp/800-38b/archive/2005-05-01
.. _`NIST PKI Testing`: https://csrc.nist.gov/Projects/PKI-Testing
.. _`testx509.pem`: https://github.com/openssl/openssl/blob/master/test/testx509.pem
-.. _`DigiCert Global Root G3`: https://cacerts.digicert.com/DigiCertGlobalRootG3.crt
+.. _`DigiCert Global Root G3`: http://cacerts.digicert.com/DigiCertGlobalRootG3.crt
.. _`root data`: https://hg.mozilla.org/projects/nss/file/25b2922cc564/security/nss/lib/ckfw/builtins/certdata.txt#l2053
.. _`asymmetric/public/PKCS1/dsa.pub.pem`: https://github.com/ruby/ruby/blob/4ccb387f3bc436a08fc6d72c4931994f5de95110/test/openssl/test_pkey_dsa.rb#L53
.. _`Mozilla bug`: https://bugzilla.mozilla.org/show_bug.cgi?id=233586
-.. _`Russian CA`: https://e-trust.gosuslugi.ru/MainCA
+.. _`Russian CA`: https://e-trust.gosuslugi.ru/
.. _`test/evptests.txt`: https://github.com/openssl/openssl/blob/2d0b44126763f989a4cbffbffe9d0c7518158bb7/test/evptests.txt
.. _`unknown signature OID`: https://bugzilla.mozilla.org/show_bug.cgi?id=405966
.. _`botan`: https://github.com/randombit/botan/blob/57789bdfc55061002b2727d0b32587612829a37c/src/tests/data/pubkey/dh.vec
.. _`DHKE`: https://sandilands.info/sgordon/diffie-hellman-secret-key-exchange-with-openssl
.. _`Botan's key wrap vectors`: https://github.com/randombit/botan/blob/737f33c09a18500e044dca3e2ae13bd2c08bafdd/src/tests/data/keywrap/nist_key_wrap.vec
+.. _`root-ed25519.pem`: https://github.com/openssl/openssl/blob/2a1e2fe145c6eb8e75aa2e1b3a8c3a49384b2852/test/certs/root-ed25519.pem
+.. _`server-ed25519-cert.pem`: https://github.com/openssl/openssl/blob/2a1e2fe145c6eb8e75aa2e1b3a8c3a49384b2852/test/certs/server-ed25519-cert.pem
+.. _`server-ed448-cert.pem`: https://github.com/openssl/openssl/blob/2a1e2fe145c6eb8e75aa2e1b3a8c3a49384b2852/test/certs/server-ed448-cert.pem
diff --git a/docs/doing-a-release.rst b/docs/doing-a-release.rst
index e7ee88fa0..043d52d28 100644
--- a/docs/doing-a-release.rst
+++ b/docs/doing-a-release.rst
@@ -21,10 +21,10 @@ Verifying OpenSSL version
-------------------------
The release process creates wheels bundling OpenSSL for Windows, macOS, and
-Linux. Check that the Windows and macOS Jenkins builders have the latest
-version of OpenSSL installed and verify that the latest version is present in
-the ``pyca/cryptography-manylinux1`` docker containers. If anything is out
-of date follow the instructions for upgrading OpenSSL.
+Linux. Check that the Windows, macOS, and Linux builders (both
+``pyca/cryptography-manylinux1`` and ``pyca/cryptography-manylinux2010``) have
+the latest OpenSSL. If anything is out of date follow the instructions for
+upgrading OpenSSL.
Upgrading OpenSSL
-----------------
diff --git a/docs/faq.rst b/docs/faq.rst
index 6d876610f..d6f4ad336 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -1,6 +1,33 @@
Frequently asked questions
==========================
+.. _faq-howto-handle-deprecation-warning:
+
+I cannot suppress the deprecation warning that ``cryptography`` emits on import
+-------------------------------------------------------------------------------
+
+.. hint::
+
+ The deprecation warning emitted on import does not inherit
+ :py:exc:`DeprecationWarning` but inherits :py:exc:`UserWarning`
+ instead.
+
+If your pytest setup follows the best practices of failing on
+emitted warnings (``filterwarnings = error``), you may ignore it
+by adding the following line at the end of the list::
+
+ ignore:Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.:UserWarning
+
+**Note:** Using ``cryptography.utils.CryptographyDeprecationWarning``
+is not possible here because specifying it triggers
+``import cryptography`` internally that emits the warning before
+the ignore rule even kicks in.
+
+Ref: https://github.com/pytest-dev/pytest/issues/7524
+
+The same applies when you use :py:func:`~warnings.filterwarnings` in
+your code or invoke CPython with :std:option:`-W` command line option.
+
``cryptography`` failed to install!
-----------------------------------
@@ -43,18 +70,17 @@ legacy libraries:
:class:`AES-GCM <cryptography.hazmat.primitives.ciphers.modes.GCM>` and
:class:`~cryptography.hazmat.primitives.kdf.hkdf.HKDF`.
-Compiling ``cryptography`` on macOS produces a ``fatal error: 'openssl/aes.h' file not found`` error
-----------------------------------------------------------------------------------------------------
+Installing ``cryptography`` produces a ``fatal error: 'openssl/opensslv.h' file not found`` error
+-------------------------------------------------------------------------------------------------
-This happens because macOS 10.11 no longer includes a copy of OpenSSL.
-``cryptography`` now provides wheels which include a statically linked copy of
-OpenSSL. You're seeing this error because your copy of pip is too old to find
-our wheel files. Upgrade your copy of pip with ``pip install -U pip`` and then
-try install ``cryptography`` again.
+``cryptography`` provides wheels which include a statically linked copy of
+OpenSSL. If you see this error it is likely because your copy of ``pip`` is too
+old to find our wheel files. Upgrade your ``pip`` with ``pip install -U pip``
+and then try to install ``cryptography`` again.
-If you are using PyPy, we do not currently ship ``cryptography`` wheels for
-PyPy. You will need to install your own copy of OpenSSL -- we recommend using
-Homebrew.
+Users on PyPy, unusual CPU architectures, or distributions of Linux using
+``musl`` (like Alpine) will need to compile ``cryptography`` themselves. Please
+view our :doc:`/installation` documentation.
``cryptography`` raised an ``InternalError`` and I'm not sure what to do?
-------------------------------------------------------------------------
@@ -82,34 +108,22 @@ Your ``pip`` and/or ``setuptools`` are outdated. Please upgrade to the latest
versions with ``pip install -U pip setuptools`` (or on Windows
``python -m pip install -U pip setuptools``).
-Installing cryptography with OpenSSL 0.9.8 or 1.0.0 fails
----------------------------------------------------------
-
-The OpenSSL project has dropped support for the 0.9.8 and 1.0.0 release series.
-Since they are no longer receiving security patches from upstream,
-``cryptography`` is also dropping support for them. To fix this issue you
-should upgrade to a newer version of OpenSSL (1.0.2 or later). This may require
-you to upgrade to a newer operating system.
-
-Why are there no wheels for Python 3.5+ on Linux or macOS?
-----------------------------------------------------------
-
-Our Python3 wheels, for macOS and Linux, are ``abi3`` wheels. This means they
-support multiple versions of Python. The Python 3.4 ``abi3`` wheel can be used
-with any version of Python greater than or equal to 3.4. Recent versions of
-``pip`` will automatically install ``abi3`` wheels.
-
-``ImportError``: ``idna`` is not installed
-------------------------------------------
-
-``cryptography`` deprecated passing :term:`U-label` strings to various X.509
-constructors in version 2.1 and in version 2.5 moved the ``idna`` dependency
-to a ``setuptools`` extra. If you see this exception you should upgrade your
-software so that it no longer depends on this deprecated feature. If that is
-not yet possible you can also install ``cryptography`` with
-``pip install cryptography[idna]`` to automatically install the missing
-dependency. This workaround will be available until the feature is fully
-removed.
+Installing cryptography with OpenSSL 0.9.8, 1.0.0, 1.0.1, 1.0.2 fails
+---------------------------------------------------------------------
+
+The OpenSSL project has dropped support for the 0.9.8, 1.0.0, 1.0.1, and 1.0.2
+release series. Since they are no longer receiving security patches from
+upstream, ``cryptography`` is also dropping support for them. To fix this issue
+you should upgrade to a newer version of OpenSSL (1.1.0 or later). This may
+require you to upgrade to a newer operating system.
+
+Why are there no wheels for my Python3.x version?
+-------------------------------------------------
+
+Our Python3 wheels are ``abi3`` wheels. This means they support multiple
+versions of Python. The ``abi3`` wheel can be used with any version of Python
+greater than or equal to the version it specifies. Recent versions of ``pip``
+will automatically install ``abi3`` wheels.
Why can't I import my PEM file?
-------------------------------
diff --git a/docs/fernet.rst b/docs/fernet.rst
index 9b95621ef..5e2655d3a 100644
--- a/docs/fernet.rst
+++ b/docs/fernet.rst
@@ -23,9 +23,10 @@ has support for implementing key rotation via :class:`MultiFernet`.
>>> f.decrypt(token)
b'my deep dark secret'
- :param bytes key: A URL-safe base64-encoded 32-byte key. This **must** be
- kept secret. Anyone with this key is able to create and
- read messages.
+ :param key: A URL-safe base64-encoded 32-byte key. This **must** be
+ kept secret. Anyone with this key is able to create and
+ read messages.
+ :type key: bytes or str
.. classmethod:: generate_key()
@@ -53,6 +54,28 @@ has support for implementing key rotation via :class:`MultiFernet`.
generated in *plaintext*, the time a message was created will
therefore be visible to a possible attacker.
+ .. method:: encrypt_at_time(data, current_time)
+
+ .. versionadded:: 3.0
+
+ Encrypts data passed using explicitly passed current time. See
+ :meth:`encrypt` for the documentation of the ``data`` parameter, the
+ return type and the exceptions raised.
+
+ The motivation behind this method is for the client code to be able to
+ test token expiration. Since this method can be used in an insecure
+ manner one should make sure the correct time (``int(time.time())``)
+ is passed as ``current_time`` outside testing.
+
+ :param int current_time: The current time.
+
+ .. note::
+
+ Similarly to :meth:`encrypt` the encrypted message contains the
+ timestamp in *plaintext*, in this case the timestamp is the value
+ of the ``current_time`` parameter.
+
+
.. method:: decrypt(token, ttl=None)
Decrypts a Fernet token. If successfully decrypted you will receive the
@@ -80,6 +103,23 @@ has support for implementing key rotation via :class:`MultiFernet`.
:raises TypeError: This exception is raised if ``token`` is not
``bytes``.
+ .. method:: decrypt_at_time(token, ttl, current_time)
+
+ .. versionadded:: 3.0
+
+ Decrypts a token using explicitly passed current time. See
+ :meth:`decrypt` for the documentation of the ``token`` and ``ttl``
+ parameters (``ttl`` is required here), the return type and the exceptions
+ raised.
+
+ The motivation behind this method is for the client code to be able to
+ test token expiration. Since this method can be used in an insecure
+ manner one should make sure the correct time (``int(time.time())``)
+ is passed as ``current_time`` outside testing.
+
+ :param int current_time: The current time.
+
+
.. method:: extract_timestamp(token)
.. versionadded:: 2.3
@@ -189,7 +229,6 @@ password through a key derivation function such as
>>> import base64
>>> import os
>>> from cryptography.fernet import Fernet
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
>>> password = b"password"
@@ -199,7 +238,6 @@ password through a key derivation function such as
... length=32,
... salt=salt,
... iterations=100000,
- ... backend=default_backend()
... )
>>> key = base64.urlsafe_b64encode(kdf.derive(password))
>>> f = Fernet(key)
@@ -236,8 +274,9 @@ Limitations
-----------
Fernet is ideal for encrypting data that easily fits in memory. As a design
-feature it does not expose unauthenticated bytes. Unfortunately, this makes it
-generally unsuitable for very large files at this time.
+feature it does not expose unauthenticated bytes. This means that the complete
+message contents must be available in memory, making Fernet generally
+unsuitable for very large files at this time.
.. _`Fernet`: https://github.com/fernet/spec/
diff --git a/docs/hazmat/backends/index.rst b/docs/hazmat/backends/index.rst
index a8a1ff301..97dbc869b 100644
--- a/docs/hazmat/backends/index.rst
+++ b/docs/hazmat/backends/index.rst
@@ -8,10 +8,13 @@ Getting a backend
.. currentmodule:: cryptography.hazmat.backends
-``cryptography`` was originally designed to support multiple backends, but
-this design has been deprecated.
+``cryptography`` was designed to support multiple cryptographic backends, but
+consumers rarely need this flexibility. Starting with version 3.1 ``backend``
+arguments are optional and the default backend will automatically be selected
+if none is specified.
-You can get the default backend by calling :func:`~default_backend`.
+On older versions you can get the default backend by calling
+:func:`~default_backend`.
.. function:: default_backend()
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index 2c2d70ec8..36dd3a7a5 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -159,14 +159,13 @@ A specific ``backend`` may provide one or more of these interfaces.
.. method:: create_cmac_ctx(algorithm)
Create a
- :class:`~cryptography.hazmat.primitives.mac.MACContext` that
+ context that
uses the specified ``algorithm`` to calculate a message authentication code.
:param algorithm: An instance of
:class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`.
- :returns:
- :class:`~cryptography.hazmat.primitives.mac.MACContext`
+ :returns: CMAC object.
.. class:: PBKDF2HMACBackend
diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst
index 07ae74a27..dd85d869a 100644
--- a/docs/hazmat/backends/openssl.rst
+++ b/docs/hazmat/backends/openssl.rst
@@ -3,7 +3,7 @@
OpenSSL backend
===============
-The `OpenSSL`_ C library. Cryptography supports OpenSSL version 1.0.1 and
+The `OpenSSL`_ C library. Cryptography supports OpenSSL version 1.1.0 and
greater.
.. data:: cryptography.hazmat.backends.openssl.backend
@@ -68,6 +68,12 @@ greater.
OS random engine
----------------
+.. note::
+
+ As of OpenSSL 1.1.1d its CSPRNG is fork-safe by default.
+ ``cryptography`` does not compile or load the custom engine on
+ these versions.
+
By default OpenSSL uses a user-space CSPRNG that is seeded from system random (
``/dev/urandom`` or ``CryptGenRandom``). This CSPRNG is not reseeded
automatically when a process calls ``fork()``. This can result in situations
@@ -106,7 +112,7 @@ seeded from the same pool as ``/dev/random``.
+------------------------------------------+------------------------------+
| Windows | ``CryptGenRandom()`` |
+------------------------------------------+------------------------------+
-| Linux >= 3.17 with working | ``getrandom(GRND_NONBLOCK)`` |
+| Linux >= 3.17 with working | ``getrandom()`` |
| ``SYS_getrandom`` syscall | |
+------------------------------------------+------------------------------+
| OpenBSD >= 5.6 | ``getentropy()`` |
diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/bindings/index.rst
deleted file mode 100644
index 655f4620d..000000000
--- a/docs/hazmat/bindings/index.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-.. hazmat::
-
-Bindings
-========
-
-.. module:: cryptography.hazmat.bindings
-
-``cryptography`` aims to provide low-level CFFI based bindings to multiple
-native C libraries. These provide no automatic initialization of the library
-and may not provide complete wrappers for its API.
-
-Using these functions directly is likely to require you to be careful in
-managing memory allocation, locking and other resources.
-
-
-Individual bindings
--------------------
-
-.. toctree::
- :maxdepth: 1
-
- openssl
diff --git a/docs/hazmat/bindings/openssl.rst b/docs/hazmat/bindings/openssl.rst
deleted file mode 100644
index ac65aa97b..000000000
--- a/docs/hazmat/bindings/openssl.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-.. hazmat::
-
-OpenSSL binding
-===============
-
-.. currentmodule:: cryptography.hazmat.bindings.openssl.binding
-
-These are `CFFI`_ bindings to the `OpenSSL`_ C library. Cryptography supports
-OpenSSL version 1.0.1 and greater.
-
-.. class:: cryptography.hazmat.bindings.openssl.binding.Binding()
-
- This is the exposed API for the OpenSSL bindings. It has two public
- attributes:
-
- .. attribute:: ffi
-
- This is a ``cffi.FFI`` instance. It can be used to allocate and
- otherwise manipulate OpenSSL structures.
-
- .. attribute:: lib
-
- This is a ``cffi`` library. It can be used to call OpenSSL functions,
- and access constants.
-
- .. classmethod:: init_static_locks
-
- Enables the best available locking callback for OpenSSL.
- See :ref:`openssl-threading`.
-
-.. _openssl-threading:
-
-Threading
----------
-
-``cryptography`` enables OpenSSLs `thread safety facilities`_ in two different
-ways depending on the configuration of your system. Normally the locking
-callbacks provided by your Python implementation specifically for OpenSSL will
-be used. However, if you have linked ``cryptography`` to a different version of
-OpenSSL than that used by your Python implementation we enable an alternative
-locking callback. This version is implemented in Python and so may result in
-lower performance in some situations. In particular parallelism is reduced
-because it has to acquire the GIL whenever any lock operations occur within
-OpenSSL.
-
-.. _`CFFI`: https://cffi.readthedocs.io
-.. _`OpenSSL`: https://www.openssl.org/
-.. _`thread safety facilities`: https://www.openssl.org/docs/man1.0.2/crypto/threads.html
diff --git a/docs/hazmat/primitives/asymmetric/dh.rst b/docs/hazmat/primitives/asymmetric/dh.rst
index edfe61436..6b47da089 100644
--- a/docs/hazmat/primitives/asymmetric/dh.rst
+++ b/docs/hazmat/primitives/asymmetric/dh.rst
@@ -31,13 +31,11 @@ present.
.. code-block:: pycon
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import dh
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
>>> # Generate some parameters. These can be reused.
- >>> parameters = dh.generate_parameters(generator=2, key_size=2048,
- ... backend=default_backend())
+ >>> parameters = dh.generate_parameters(generator=2, key_size=2048)
>>> # Generate a private key for use in the exchange.
>>> server_private_key = parameters.generate_private_key()
>>> # In a real handshake the peer is a remote client. For this
@@ -51,7 +49,6 @@ present.
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key)
>>> # And now we can demonstrate that the handshake performed in the
>>> # opposite direction gives the same final value
@@ -63,7 +60,6 @@ present.
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(same_shared_key)
>>> derived_key == same_derived_key
@@ -75,13 +71,11 @@ example of the ephemeral form:
.. code-block:: pycon
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import dh
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
>>> # Generate some parameters. These can be reused.
- >>> parameters = dh.generate_parameters(generator=2, key_size=2048,
- ... backend=default_backend())
+ >>> parameters = dh.generate_parameters(generator=2, key_size=2048)
>>> # Generate a private key for use in the exchange.
>>> private_key = parameters.generate_private_key()
>>> # In a real handshake the peer_public_key will be received from the
@@ -96,7 +90,6 @@ example of the ephemeral form:
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key)
>>> # For the next handshake we MUST generate another private key, but
>>> # we can reuse the parameters.
@@ -108,7 +101,6 @@ example of the ephemeral form:
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key_2)
To assemble a :class:`~DHParameters` and a :class:`~DHPublicKey` from
@@ -118,9 +110,9 @@ example, if **p**, **g**, and **y** are :class:`int` objects received from a
peer::
pn = dh.DHParameterNumbers(p, g)
- parameters = pn.parameters(default_backend())
+ parameters = pn.parameters()
peer_public_numbers = dh.DHPublicNumbers(y, pn)
- peer_public_key = peer_public_numbers.public_key(default_backend())
+ peer_public_key = peer_public_numbers.public_key()
See also the :class:`~cryptography.hazmat.backends.interfaces.DHBackend`
@@ -129,7 +121,7 @@ API for additional functionality.
Group parameters
~~~~~~~~~~~~~~~~
-.. function:: generate_parameters(generator, key_size, backend)
+.. function:: generate_parameters(generator, key_size, backend=None)
.. versionadded:: 1.7
@@ -140,7 +132,7 @@ Group parameters
:param key_size: The bit length of the prime modulus to generate.
- :param backend: A
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.DHBackend`
instance.
@@ -349,11 +341,11 @@ Numbers
p subgroup order value.
- .. method:: parameters(backend)
+ .. method:: parameters(backend=None)
.. versionadded:: 1.7
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DHBackend`.
:returns: A new instance of :class:`DHParameters`.
@@ -377,11 +369,11 @@ Numbers
The private value.
- .. method:: private_key(backend)
+ .. method:: private_key(backend=None)
.. versionadded:: 1.7
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DHBackend`.
:returns: A new instance of :class:`DHPrivateKey`.
@@ -405,11 +397,11 @@ Numbers
The public value.
- .. method:: public_key(backend)
+ .. method:: public_key(backend=None)
.. versionadded:: 1.7
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DHBackend`.
:returns: A new instance of :class:`DHPublicKey`.
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 7b0598693..788e4270b 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -5,26 +5,36 @@ DSA
.. module:: cryptography.hazmat.primitives.asymmetric.dsa
+.. note::
+
+ DSA is a **legacy algorithm** and should generally be avoided in favor of
+ choices like
+ :doc:`EdDSA using curve25519</hazmat/primitives/asymmetric/ed25519>` or
+ :doc:`ECDSA</hazmat/primitives/asymmetric/ec>`.
+
`DSA`_ is a `public-key`_ algorithm for signing messages.
Generation
~~~~~~~~~~
-.. function:: generate_private_key(key_size, backend)
+.. function:: generate_private_key(key_size, backend=None)
.. versionadded:: 0.5
+ .. versionchanged:: 3.0
+
+ Added support for 4096-bit keys for some legacy applications that
+ continue to use DSA despite the wider cryptographic community's
+ `ongoing protestations`_.
+
Generate a DSA private key from the given key size. This function will
generate a new set of parameters and key in one step.
:param int key_size: The length of the modulus in :term:`bits`. It should
- be either 1024, 2048 or 3072. For keys generated in 2015 this should
- be `at least 2048`_ (See page 41). Note that some applications
- (such as SSH) have not yet gained support for larger key sizes
- specified in FIPS 186-3 and are still restricted to only the
- 1024-bit keys specified in FIPS 186-2.
+ be either 1024, 2048, 3072, or 4096. For keys generated in 2015 this
+ should be `at least 2048`_ (See page 41).
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
:return: An instance of
@@ -34,20 +44,23 @@ Generation
the provided ``backend`` does not implement
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`
-.. function:: generate_parameters(key_size, backend)
+.. function:: generate_parameters(key_size, backend=None)
.. versionadded:: 0.5
+ .. versionchanged:: 3.0
+
+ Added support for 4096-bit keys for some legacy applications that
+ continue to use DSA despite the wider cryptographic community's
+ `ongoing protestations`_.
+
Generate DSA parameters using the provided ``backend``.
:param int key_size: The length of :attr:`~DSAParameterNumbers.q`. It
- should be either 1024, 2048 or 3072. For keys generated in 2015 this
- should be `at least 2048`_ (See page 41). Note that some applications
- (such as SSH) have not yet gained support for larger key sizes
- specified in FIPS 186-3 and are still restricted to only the
- 1024-bit keys specified in FIPS 186-2.
+ should be either 1024, 2048, 3072, or 4096. For keys generated in 2015
+ this should be `at least 2048`_ (See page 41).
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
:return: An instance of
@@ -65,12 +78,10 @@ instance.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import dsa
>>> private_key = dsa.generate_private_key(
... key_size=1024,
- ... backend=default_backend()
... )
>>> data = b"this is some data I'd like to sign"
>>> signature = private_key.sign(
@@ -90,7 +101,7 @@ separately and pass that value using
>>> from cryptography.hazmat.primitives.asymmetric import utils
>>> chosen_hash = hashes.SHA256()
- >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher = hashes.Hash(chosen_hash)
>>> hasher.update(b"data & ")
>>> hasher.update(b"more data")
>>> digest = hasher.finalize()
@@ -133,7 +144,7 @@ separately and pass that value using
.. doctest::
>>> chosen_hash = hashes.SHA256()
- >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher = hashes.Hash(chosen_hash)
>>> hasher.update(b"data & ")
>>> hasher.update(b"more data")
>>> digest = hasher.finalize()
@@ -170,9 +181,9 @@ Numbers
The generator.
- .. method:: parameters(backend)
+ .. method:: parameters(backend=None)
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
:returns: A new instance of
@@ -197,9 +208,9 @@ Numbers
The :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameterNumbers`
associated with the public key.
- .. method:: public_key(backend)
+ .. method:: public_key(backend=None)
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
:returns: A new instance of
@@ -229,9 +240,9 @@ Numbers
The :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`
associated with the private key.
- .. method:: private_key(backend)
+ .. method:: private_key(backend=None)
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
:returns: A new instance of
@@ -344,7 +355,8 @@ Key interfaces
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`),
format (
- :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`,
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
or
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`)
and encryption algorithm (such as
@@ -445,3 +457,4 @@ Key interfaces
.. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography
.. _`FIPS 186-4`: https://csrc.nist.gov/publications/detail/fips/186/4/final
.. _`at least 2048`: https://www.cosic.esat.kuleuven.be/ecrypt/ecrypt2/documents/D.SPA.20.pdf
+.. _`ongoing protestations`: https://buttondown.email/cryptography-dispatches/archive/cryptography-dispatches-dsa-is-past-its-prime/
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index d89fde3da..5691560f3 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -6,7 +6,7 @@ Elliptic curve cryptography
.. module:: cryptography.hazmat.primitives.asymmetric.ec
-.. function:: generate_private_key(curve, backend)
+.. function:: generate_private_key(curve, backend=None)
.. versionadded:: 0.5
@@ -14,13 +14,13 @@ Elliptic curve cryptography
:param curve: An instance of :class:`EllipticCurve`.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
:returns: A new instance of :class:`EllipticCurvePrivateKey`.
-.. function:: derive_private_key(private_value, curve, backend)
+.. function:: derive_private_key(private_value, curve, backend=None)
.. versionadded:: 1.6
@@ -31,7 +31,7 @@ Elliptic curve cryptography
:param curve: An instance of :class:`EllipticCurve`.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
:returns: A new instance of :class:`EllipticCurvePrivateKey`.
@@ -47,16 +47,19 @@ Elliptic Curve Signature Algorithms
The ECDSA signature algorithm first standardized in NIST publication
`FIPS 186-3`_, and later in `FIPS 186-4`_.
+ Note that while elliptic curve keys can be used for both signing and key
+ exchange, this is `bad cryptographic practice`_. Instead, users should
+ generate separate signing and ECDH keys.
+
:param algorithm: An instance of
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import ec
>>> private_key = ec.generate_private_key(
- ... ec.SECP384R1(), default_backend()
+ ... ec.SECP384R1()
... )
>>> data = b"this is some data I'd like to sign"
>>> signature = private_key.sign(
@@ -64,7 +67,7 @@ Elliptic Curve Signature Algorithms
... ec.ECDSA(hashes.SHA256())
... )
- The ``signature`` is a ``bytes`` object, whose contents is DER encoded as
+ The ``signature`` is a ``bytes`` object, whose contents are DER encoded as
described in :rfc:`3279`. This can be decoded using
:func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`.
@@ -76,7 +79,7 @@ Elliptic Curve Signature Algorithms
>>> from cryptography.hazmat.primitives.asymmetric import utils
>>> chosen_hash = hashes.SHA256()
- >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher = hashes.Hash(chosen_hash)
>>> hasher.update(b"data & ")
>>> hasher.update(b"more data")
>>> digest = hasher.finalize()
@@ -86,13 +89,18 @@ Elliptic Curve Signature Algorithms
... )
- Verification requires the public key, the signature itself, the signed
- data, and knowledge of the hashing algorithm that was used when producing
- the signature:
+ Verification requires the public key, the DER-encoded signature itself, the
+ signed data, and knowledge of the hashing algorithm that was used when
+ producing the signature:
>>> public_key = private_key.public_key()
>>> public_key.verify(signature, data, ec.ECDSA(hashes.SHA256()))
+ As above, the ``signature`` is a ``bytes`` object whose contents are DER
+ encoded as described in :rfc:`3279`. It can be created from a raw ``(r,s)``
+ pair by using
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`.
+
If the signature is not valid, an
:class:`~cryptography.exceptions.InvalidSignature` exception will be raised.
@@ -103,7 +111,7 @@ Elliptic Curve Signature Algorithms
.. doctest::
>>> chosen_hash = hashes.SHA256()
- >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher = hashes.Hash(chosen_hash)
>>> hasher.update(b"data & ")
>>> hasher.update(b"more data")
>>> digest = hasher.finalize()
@@ -139,12 +147,12 @@ Elliptic Curve Signature Algorithms
The private value.
- .. method:: private_key(backend)
+ .. method:: private_key(backend=None)
Convert a collection of numbers into a private key suitable for doing
actual cryptographic operations.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
:returns: A new instance of :class:`EllipticCurvePrivateKey`.
@@ -181,12 +189,12 @@ Elliptic Curve Signature Algorithms
The affine y component of the public point used for verifying.
- .. method:: public_key(backend)
+ .. method:: public_key(backend=None)
Convert a collection of numbers into a public key suitable for doing
actual cryptographic operations.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
:raises ValueError: Raised if the point is invalid for the curve.
@@ -249,6 +257,10 @@ Elliptic Curve Key Exchange algorithm
key, derivation of multiple keys, and destroys any structure that may be
present.
+ Note that while elliptic curve keys can be used for both signing and key
+ exchange, this is `bad cryptographic practice`_. Instead, users should
+ generate separate signing and ECDH keys.
+
.. warning::
This example does not give `forward secrecy`_ and is only provided as a
@@ -257,18 +269,17 @@ Elliptic Curve Key Exchange algorithm
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import ec
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
>>> # Generate a private key for use in the exchange.
>>> server_private_key = ec.generate_private_key(
- ... ec.SECP384R1(), default_backend()
+ ... ec.SECP384R1()
... )
>>> # In a real handshake the peer is a remote client. For this
>>> # example we'll generate another local private key though.
>>> peer_private_key = ec.generate_private_key(
- ... ec.SECP384R1(), default_backend()
+ ... ec.SECP384R1()
... )
>>> shared_key = server_private_key.exchange(
... ec.ECDH(), peer_private_key.public_key())
@@ -278,7 +289,6 @@ Elliptic Curve Key Exchange algorithm
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key)
>>> # And now we can demonstrate that the handshake performed in the
>>> # opposite direction gives the same final value
@@ -290,7 +300,6 @@ Elliptic Curve Key Exchange algorithm
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(same_shared_key)
>>> derived_key == same_derived_key
True
@@ -303,19 +312,18 @@ Elliptic Curve Key Exchange algorithm
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import ec
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
>>> # Generate a private key for use in the exchange.
>>> private_key = ec.generate_private_key(
- ... ec.SECP384R1(), default_backend()
+ ... ec.SECP384R1()
... )
>>> # In a real handshake the peer_public_key will be received from the
>>> # other party. For this example we'll generate another private key
>>> # and get a public key from that.
>>> peer_public_key = ec.generate_private_key(
- ... ec.SECP384R1(), default_backend()
+ ... ec.SECP384R1()
... ).public_key()
>>> shared_key = private_key.exchange(ec.ECDH(), peer_public_key)
>>> # Perform key derivation.
@@ -324,14 +332,13 @@ Elliptic Curve Key Exchange algorithm
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key)
>>> # For the next handshake we MUST generate another private key.
>>> private_key_2 = ec.generate_private_key(
- ... ec.SECP384R1(), default_backend()
+ ... ec.SECP384R1()
... )
>>> peer_public_key_2 = ec.generate_private_key(
- ... ec.SECP384R1(), default_backend()
+ ... ec.SECP384R1()
... ).public_key()
>>> shared_key_2 = private_key_2.exchange(ec.ECDH(), peer_public_key_2)
>>> derived_key_2 = HKDF(
@@ -339,7 +346,6 @@ Elliptic Curve Key Exchange algorithm
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key_2)
Elliptic Curves
@@ -601,7 +607,16 @@ Key Interfaces
:param signature_algorithm: An instance of
:class:`EllipticCurveSignatureAlgorithm`, such as :class:`ECDSA`.
- :return bytes: Signature.
+ :return bytes: The signature as a ``bytes`` object, whose contents are
+ DER encoded as described in :rfc:`3279`. This can be decoded using
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature`,
+ which returns the decoded tuple ``(r, s)``.
+
+ .. attribute:: curve
+
+ :type: :class:`EllipticCurve`
+
+ The EllipticCurve that this key is on.
.. attribute:: key_size
@@ -633,7 +648,8 @@ Key Interfaces
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`),
format (
- :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`,
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
or
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`)
and encryption algorithm (such as
@@ -704,7 +720,10 @@ Key Interfaces
Verify one block of data was signed by the private key associated
with this public key.
- :param bytes signature: The signature to verify.
+ :param bytes signature: The DER-encoded signature to verify.
+ A raw signature may be DER-encoded by splitting it into the ``r``
+ and ``s`` components and passing them into
+ :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`.
:param bytes data: The message string that was signed.
@@ -761,12 +780,10 @@ This sample demonstrates how to generate a private key and serialize it.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
- >>> from cryptography.hazmat.primitives import hashes
- >>> from cryptography.hazmat.primitives.asymmetric import ec
>>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import ec
- >>> private_key = ec.generate_private_key(ec.SECP384R1(), default_backend())
+ >>> private_key = ec.generate_private_key(ec.SECP384R1())
>>> serialized_private = private_key.private_bytes(
... encoding=serialization.Encoding.PEM,
@@ -806,14 +823,12 @@ in PEM format.
>>> loaded_public_key = serialization.load_pem_public_key(
... serialized_public,
- ... backend=default_backend()
... )
>>> loaded_private_key = serialization.load_pem_private_key(
... serialized_private,
... # or password=None, if in plain text
... password=b'testpassword',
- ... backend=default_backend()
... )
@@ -926,6 +941,21 @@ Elliptic Curve Object Identifiers
Corresponds to the dotted string ``"1.3.132.0.39"``.
+.. function:: get_curve_for_oid(oid)
+
+ .. versionadded:: 2.6
+
+ A function that takes an :class:`~cryptography.x509.ObjectIdentifier`
+ and returns the associated elliptic curve class.
+
+ :param oid: An instance of
+ :class:`~cryptography.x509.ObjectIdentifier`.
+
+ :returns: The matching elliptic curve class. The returned class conforms
+ to the :class:`EllipticCurve` interface.
+
+ :raises LookupError: Raised if no elliptic curve is found that matches
+ the provided object identifier.
.. _`FIPS 186-3`: https://csrc.nist.gov/csrc/media/publications/fips/186/3/archive/2009-06-25/documents/fips_186-3.pdf
.. _`FIPS 186-4`: https://csrc.nist.gov/publications/detail/fips/186/4/final
@@ -939,4 +969,5 @@ Elliptic Curve Object Identifiers
.. _`ECDSA`: https://en.wikipedia.org/wiki/ECDSA
.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
.. _`forward secrecy`: https://en.wikipedia.org/wiki/Forward_secrecy
-.. _`SEC 1 v2.0`: http://www.secg.org/sec1-v2.pdf
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
+.. _`bad cryptographic practice`: https://crypto.stackexchange.com/a/3313
diff --git a/docs/hazmat/primitives/asymmetric/ed25519.rst b/docs/hazmat/primitives/asymmetric/ed25519.rst
new file mode 100644
index 000000000..47d95ec1b
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/ed25519.rst
@@ -0,0 +1,168 @@
+.. hazmat::
+
+Ed25519 signing
+===============
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ed25519
+
+
+Ed25519 is an elliptic curve signing algorithm using `EdDSA`_ and
+`Curve25519`_. If you do not have legacy interoperability concerns then you
+should strongly consider using this signature algorithm.
+
+
+Signing & Verification
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
+ >>> private_key = Ed25519PrivateKey.generate()
+ >>> signature = private_key.sign(b"my authenticated message")
+ >>> public_key = private_key.public_key()
+ >>> # Raises InvalidSignature if verification fails
+ >>> public_key.verify(signature, b"my authenticated message")
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: Ed25519PrivateKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: generate()
+
+ Generate an Ed25519 private key.
+
+ :returns: :class:`Ed25519PrivateKey`
+
+ .. classmethod:: from_private_bytes(data)
+
+ :param data: 32 byte private key.
+ :type data: :term:`bytes-like`
+
+ :returns: :class:`Ed25519PrivateKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import ed25519
+ >>> private_key = ed25519.Ed25519PrivateKey.generate()
+ >>> private_bytes = private_key.private_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PrivateFormat.Raw,
+ ... encryption_algorithm=serialization.NoEncryption()
+ ... )
+ >>> loaded_private_key = ed25519.Ed25519PrivateKey.from_private_bytes(private_bytes)
+
+
+ .. method:: public_key()
+
+ :returns: :class:`Ed25519PublicKey`
+
+ .. method:: sign(data)
+
+ :param bytes data: The data to sign.
+
+ :returns bytes: The 64 byte signature.
+
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`,
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8` or
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`.
+
+ :param encryption_algorithm: An instance of an object conforming to the
+ :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+ interface.
+
+ :return bytes: Serialized key.
+
+.. class:: Ed25519PublicKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: from_public_bytes(data)
+
+ :param bytes data: 32 byte public key.
+
+ :returns: :class:`Ed25519PublicKey`
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import serialization
+ >>> from cryptography.hazmat.primitives.asymmetric import ed25519
+ >>> private_key = ed25519.Ed25519PrivateKey.generate()
+ >>> public_key = private_key.public_key()
+ >>> public_bytes = public_key.public_bytes(
+ ... encoding=serialization.Encoding.Raw,
+ ... format=serialization.PublicFormat.Raw
+ ... )
+ >>> loaded_public_key = ed25519.Ed25519PublicKey.from_public_bytes(public_bytes)
+
+ .. method:: public_bytes(encoding, format)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.OpenSSH`,
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`,
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.OpenSSH`
+ , or
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`.
+ If ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.OpenSSH`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.OpenSSH`.
+ In all other cases ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
+
+ :returns bytes: The public key bytes.
+
+ .. method:: verify(signature, data)
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The data to verify.
+
+ :raises cryptography.exceptions.InvalidSignature: Raised when the
+ signature cannot be verified.
+
+
+
+.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
+.. _`Curve25519`: https://en.wikipedia.org/wiki/Curve25519
diff --git a/docs/hazmat/primitives/asymmetric/ed448.rst b/docs/hazmat/primitives/asymmetric/ed448.rst
new file mode 100644
index 000000000..fb79dcb61
--- /dev/null
+++ b/docs/hazmat/primitives/asymmetric/ed448.rst
@@ -0,0 +1,131 @@
+.. hazmat::
+
+Ed448 signing
+=============
+
+.. currentmodule:: cryptography.hazmat.primitives.asymmetric.ed448
+
+
+Ed448 is an elliptic curve signing algorithm using `EdDSA`_.
+
+
+Signing & Verification
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. doctest::
+
+ >>> from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PrivateKey
+ >>> private_key = Ed448PrivateKey.generate()
+ >>> signature = private_key.sign(b"my authenticated message")
+ >>> public_key = private_key.public_key()
+ >>> # Raises InvalidSignature if verification fails
+ >>> public_key.verify(signature, b"my authenticated message")
+
+Key interfaces
+~~~~~~~~~~~~~~
+
+.. class:: Ed448PrivateKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: generate()
+
+ Generate an Ed448 private key.
+
+ :returns: :class:`Ed448PrivateKey`
+
+ .. classmethod:: from_private_bytes(data)
+
+ :param data: 57 byte private key.
+ :type data: :term:`bytes-like`
+
+ :returns: :class:`Ed448PrivateKey`
+
+ .. method:: public_key()
+
+ :returns: :class:`Ed448PublicKey`
+
+ .. method:: sign(data)
+
+ :param bytes data: The data to sign.
+
+ :returns bytes: The 114 byte signature.
+
+ .. method:: private_bytes(encoding, format, encryption_algorithm)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`.
+
+ :param encryption_algorithm: An instance of an object conforming to the
+ :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+ interface.
+
+ :return bytes: Serialized key.
+
+.. class:: Ed448PublicKey
+
+ .. versionadded:: 2.6
+
+ .. classmethod:: from_public_bytes(data)
+
+ :param bytes data: 57 byte public key.
+
+ :returns: :class:`Ed448PublicKey`
+
+ .. method:: public_bytes(encoding, format)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`
+ or
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ ) are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
+ enum. If the ``encoding`` is
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
+ then ``format`` must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
+ , otherwise it must be
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
+
+ :returns bytes: The public key bytes.
+
+ .. method:: verify(signature, data)
+
+ :param bytes signature: The signature to verify.
+
+ :param bytes data: The data to verify.
+
+ :raises cryptography.exceptions.InvalidSignature: Raised when the
+ signature cannot be verified.
+
+
+
+.. _`EdDSA`: https://en.wikipedia.org/wiki/EdDSA
diff --git a/docs/hazmat/primitives/asymmetric/index.rst b/docs/hazmat/primitives/asymmetric/index.rst
index 1561c59f1..c27e1781e 100644
--- a/docs/hazmat/primitives/asymmetric/index.rst
+++ b/docs/hazmat/primitives/asymmetric/index.rst
@@ -23,7 +23,9 @@ private key is able to decrypt it.
.. toctree::
:maxdepth: 1
+ ed25519
x25519
+ ed448
x448
ec
rsa
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index dab909646..33f402b65 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -14,10 +14,14 @@ Unlike symmetric cryptography, where the key is typically just a random series
of bytes, RSA keys have a complex internal structure with `specific
mathematical properties`_.
-.. function:: generate_private_key(public_exponent, key_size, backend)
+.. function:: generate_private_key(public_exponent, key_size, backend=None)
.. versionadded:: 0.5
+ .. versionchanged:: 3.0
+
+ Tightened restrictions on ``public_exponent``.
+
Generates a new RSA private key using the provided ``backend``.
``key_size`` describes how many :term:`bits` long the key should be. Larger
keys provide more security; currently ``1024`` and below are considered
@@ -28,24 +32,22 @@ mathematical properties`_.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> private_key = rsa.generate_private_key(
... public_exponent=65537,
... key_size=2048,
- ... backend=default_backend()
... )
:param int public_exponent: The public exponent of the new key.
- Usually one of the small Fermat primes 3, 5, 17, 257, 65537. If in
- doubt you should `use 65537`_.
+ Either 65537 or 3 (for legacy purposes). Almost everyone should
+ `use 65537`_.
:param int key_size: The length of the modulus in :term:`bits`. For keys
generated in 2015 it is strongly recommended to be
`at least 2048`_ (See page 41). It must not be less than 512.
Some backends may have additional limitations.
- :param backend: A backend which implements
+ :param backend: An optional backend which implements
:class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
:return: An instance of
@@ -64,14 +66,12 @@ markers), you can load it:
.. code-block:: pycon
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import serialization
>>> with open("path/to/key.pem", "rb") as key_file:
... private_key = serialization.load_pem_private_key(
... key_file.read(),
... password=None,
- ... backend=default_backend()
... )
Serialized keys may optionally be encrypted on disk using a password. In this
@@ -167,7 +167,7 @@ separately and pass that value using
>>> from cryptography.hazmat.primitives.asymmetric import utils
>>> chosen_hash = hashes.SHA256()
- >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher = hashes.Hash(chosen_hash)
>>> hasher.update(b"data & ")
>>> hasher.update(b"more data")
>>> digest = hasher.finalize()
@@ -217,7 +217,7 @@ separately and pass that value using
.. doctest::
>>> chosen_hash = hashes.SHA256()
- >>> hasher = hashes.Hash(chosen_hash, default_backend())
+ >>> hasher = hashes.Hash(chosen_hash)
>>> hasher.update(b"data & ")
>>> hasher.update(b"more data")
>>> digest = hasher.finalize()
@@ -342,6 +342,11 @@ Padding
:class:`OAEP` should be preferred for encryption and :class:`PSS` should be
preferred for signatures.
+ .. warning::
+
+ Our implementation of PKCS1 v1.5 decryption is not constant time. See
+ :doc:`/limitations` for details.
+
.. function:: calculate_max_pss_salt_length(key, hash_algorithm)
@@ -399,9 +404,9 @@ is unavailable.
The public exponent.
- .. method:: public_key(backend)
+ .. method:: public_key(backend=None)
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
:returns: A new instance of
@@ -466,9 +471,9 @@ is unavailable.
A `Chinese remainder theorem`_ coefficient used to speed up RSA
operations. Calculated as: q\ :sup:`-1` mod p
- .. method:: private_key(backend)
+ .. method:: private_key(backend=None)
- :param backend: A new instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
:returns: An instance of
@@ -607,7 +612,8 @@ Key interfaces
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`),
format (
- :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL`,
+ :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.OpenSSH`
or
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`)
and encryption algorithm (such as
@@ -708,6 +714,55 @@ Key interfaces
:raises cryptography.exceptions.InvalidSignature: If the signature does
not validate.
+ .. method:: recover_data_from_signature(signature, padding, algorithm)
+
+ .. versionadded:: 3.3
+
+ Recovers the signed data from the signature. The data contains the
+ digest of the original message string. The ``padding`` and
+ ``algorithm`` parameters must match the ones used when the signature
+ was created for the recovery to succeed.
+
+ The ``algorithm`` parameter can also be set to ``None`` to recover all
+ the data present in the signature, without regard to its format or the
+ hash algorithm used for its creation.
+
+ For
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15`
+ padding, this returns the data after removing the padding layer. For
+ standard signatures the data contains the full ``DigestInfo`` structure.
+ For non-standard signatures, any data can be returned, including zero-
+ length data.
+
+ Normally you should use the
+ :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.verify`
+ function to validate the signature. But for some non-standard signature
+ formats you may need to explicitly recover and validate the signed
+ data. Following are some examples:
+
+ - Some old Thawte and Verisign timestamp certificates without ``DigestInfo``.
+ - Signed MD5/SHA1 hashes in TLS 1.1 or earlier (RFC 4346, section 4.7).
+ - IKE version 1 signatures without ``DigestInfo`` (RFC 2409, section 5.1).
+
+ :param bytes signature: The signature.
+
+ :param padding: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`.
+ Recovery is only supported with some of the padding types. (Currently
+ only with
+ :class:`~cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15`).
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+ Can be ``None`` to return the all the data present in the signature.
+
+ :return bytes: The signed data.
+
+ :raises cryptography.exceptions.InvalidSignature: If the signature is
+ invalid.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If signature
+ data recovery is not supported with the provided ``padding`` type.
.. class:: RSAPublicKeyWithSerialization
diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst
index dbb2bb63e..2324340e1 100644
--- a/docs/hazmat/primitives/asymmetric/serialization.rst
+++ b/docs/hazmat/primitives/asymmetric/serialization.rst
@@ -88,10 +88,9 @@ methods.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.asymmetric import dsa, rsa
>>> from cryptography.hazmat.primitives.serialization import load_pem_private_key
- >>> key = load_pem_private_key(pem_data, password=None, backend=default_backend())
+ >>> key = load_pem_private_key(pem_data, password=None)
>>> if isinstance(key, rsa.RSAPrivateKey):
... signature = sign_with_rsa_key(key, message)
... elif isinstance(key, dsa.DSAPrivateKey):
@@ -126,7 +125,7 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
extract the public key with
:meth:`Certificate.public_key <cryptography.x509.Certificate.public_key>`.
-.. function:: load_pem_private_key(data, password, backend)
+.. function:: load_pem_private_key(data, password, backend=None)
.. versionadded:: 0.6
@@ -140,7 +139,7 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
be ``None`` if the private key is not encrypted.
:type data: :term:`bytes-like`
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
:returns: One of
@@ -159,10 +158,9 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
password was supplied.
:raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
- is of a type that is not supported by the backend or if the key is
- encrypted with a symmetric cipher that is not supported by the backend.
+ is of a type that is not supported by the backend.
-.. function:: load_pem_public_key(data, backend)
+.. function:: load_pem_public_key(data, backend=None)
.. versionadded:: 0.6
@@ -173,13 +171,13 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
.. doctest::
>>> from cryptography.hazmat.primitives.serialization import load_pem_public_key
- >>> key = load_pem_public_key(public_pem_data, backend=default_backend())
+ >>> key = load_pem_public_key(public_pem_data)
>>> isinstance(key, rsa.RSAPublicKey)
True
:param bytes data: The PEM encoded key data.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
@@ -197,7 +195,7 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
:raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
is of a type that is not supported by the backend.
-.. function:: load_pem_parameters(data, backend)
+.. function:: load_pem_parameters(data, backend=None)
.. versionadded:: 2.0
@@ -208,13 +206,13 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
>>> from cryptography.hazmat.primitives.serialization import load_pem_parameters
>>> from cryptography.hazmat.primitives.asymmetric import dh
- >>> parameters = load_pem_parameters(parameters_pem_data, backend=default_backend())
+ >>> parameters = load_pem_parameters(parameters_pem_data)
>>> isinstance(parameters, dh.DHParameters)
True
:param bytes data: The PEM encoded parameters data.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`.
@@ -236,7 +234,7 @@ data is binary. DER keys may be in a variety of formats, but as long as you
know whether it is a public or private key the loading functions will handle
the rest.
-.. function:: load_der_private_key(data, password, backend)
+.. function:: load_der_private_key(data, password, backend=None)
.. versionadded:: 0.8
@@ -250,7 +248,7 @@ the rest.
be ``None`` if the private key is not encrypted.
:type password: :term:`bytes-like`
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
:returns: One of
@@ -268,20 +266,18 @@ the rest.
not encrypted. Or if the key was encrypted but no
password was supplied.
- :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key is of a type that
- is not supported by the backend or if the key is encrypted with a
- symmetric cipher that is not supported by the backend.
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key
+ is of a type that is not supported by the backend.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> from cryptography.hazmat.primitives.serialization import load_der_private_key
- >>> key = load_der_private_key(der_data, password=None, backend=default_backend())
+ >>> key = load_der_private_key(der_data, password=None)
>>> isinstance(key, rsa.RSAPrivateKey)
True
-.. function:: load_der_public_key(data, backend)
+.. function:: load_der_public_key(data, backend=None)
.. versionadded:: 0.8
@@ -291,7 +287,7 @@ the rest.
:param bytes data: The DER encoded key data.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
:returns: One of
@@ -310,14 +306,13 @@ the rest.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> from cryptography.hazmat.primitives.serialization import load_der_public_key
- >>> key = load_der_public_key(public_der_data, backend=default_backend())
+ >>> key = load_der_public_key(public_der_data)
>>> isinstance(key, rsa.RSAPublicKey)
True
-.. function:: load_der_parameters(data, backend)
+.. function:: load_der_parameters(data, backend=None)
.. versionadded:: 2.0
@@ -326,7 +321,7 @@ the rest.
:param bytes data: The DER encoded parameters data.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`.
:returns: Currently only
@@ -341,10 +336,9 @@ the rest.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.asymmetric import dh
>>> from cryptography.hazmat.primitives.serialization import load_der_parameters
- >>> parameters = load_der_parameters(parameters_der_data, backend=default_backend())
+ >>> parameters = load_der_parameters(parameters_der_data)
>>> isinstance(parameters, dh.DHParameters)
True
@@ -369,20 +363,18 @@ DSA keys look almost identical but begin with ``ssh-dss`` rather than
``ssh-rsa``. ECDSA keys have a slightly different format, they begin with
``ecdsa-sha2-{curve}``.
-.. function:: load_ssh_public_key(data, backend)
+.. function:: load_ssh_public_key(data, backend=None)
.. versionadded:: 0.7
- Deserialize a public key from OpenSSH (:rfc:`4253`) encoded data to an
+ Deserialize a public key from OpenSSH (:rfc:`4253` and
+ `PROTOCOL.certkeys`_) encoded data to an
instance of the public key type for the specified backend.
- .. note::
-
- Currently Ed25519 keys are not supported.
-
- :param bytes data: The OpenSSH encoded key data.
+ :param data: The OpenSSH encoded key data.
+ :type data: :term:`bytes-like`
- :param backend: A backend which implements
+ :param backend: An optional backend which implements
:class:`~cryptography.hazmat.backends.interfaces.RSABackend`,
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`, or
:class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
@@ -391,8 +383,9 @@ DSA keys look almost identical but begin with ``ssh-dss`` rather than
:returns: One of
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
- or
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ , or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`,
depending on the contents of ``data``.
:raises ValueError: If the OpenSSH data could not be properly decoded or
@@ -401,6 +394,58 @@ DSA keys look almost identical but begin with ``ssh-dss`` rather than
:raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized
key is of a type that is not supported.
+OpenSSH Private Key
+~~~~~~~~~~~~~~~~~~~
+
+The format used by OpenSSH to store private keys, as approximately specified
+in `PROTOCOL.key`_.
+
+An example ECDSA key in OpenSSH format::
+
+ -----BEGIN OPENSSH PRIVATE KEY-----
+ b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
+ 1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQRI0fWnI1CxX7qYqp0ih6bxjhGmUrZK
+ /Axf8vhM8Db3oH7CFR+JdL715lUdu4XCWvQZKVf60/h3kBFhuxQC23XjAAAAqKPzVaOj81
+ WjAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEjR9acjULFfupiq
+ nSKHpvGOEaZStkr8DF/y+EzwNvegfsIVH4l0vvXmVR27hcJa9BkpV/rT+HeQEWG7FALbde
+ MAAAAga/VGV2asRlL3kXXao0aochQ59nXHA2xEGeAoQd952r0AAAAJbWFya29AdmZmAQID
+ BAUGBw==
+ -----END OPENSSH PRIVATE KEY-----
+
+.. function:: load_ssh_private_key(data, password, backend=None)
+
+ .. versionadded:: 3.0
+
+ Deserialize a private key from OpenSSH encoded data to an
+ instance of the private key type for the specified backend.
+
+ :param data: The PEM encoded OpenSSH private key data.
+ :type data: :term:`bytes-like`
+
+ :param bytes password: Password bytes to use to decrypt
+ password-protected key. Or ``None`` if not needed.
+
+ :param backend: An optional backend which implements
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend`,
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`, or
+ :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`
+ depending on the key's type.
+
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey`,
+ depending on the contents of ``data``.
+
+ :raises ValueError: If the OpenSSH data could not be properly decoded,
+ if the key is not in the proper format or the incorrect password
+ was provided.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized
+ key is of a type that is not supported.
+
PKCS12
~~~~~~
@@ -415,7 +460,7 @@ file suffix.
``cryptography`` only supports a single private key and associated
certificates when parsing PKCS12 files at this time.
-.. function:: load_key_and_certificates(data, password, backend)
+.. function:: load_key_and_certificates(data, password, backend=None)
.. versionadded:: 2.5
@@ -428,7 +473,7 @@ file suffix.
if the PKCS12 is not encrypted.
:type password: :term:`bytes-like`
- :param backend: A backend instance.
+ :param backend: An optional backend instance.
:returns: A tuple of
``(private_key, certificate, additional_certificates)``.
@@ -438,6 +483,240 @@ file suffix.
``additional_certificates`` is a list of all other
:class:`~cryptography.x509.Certificate` instances in the PKCS12 object.
+.. function:: serialize_key_and_certificates(name, key, cert, cas, encryption_algorithm)
+
+ .. versionadded:: 3.0
+
+ .. warning::
+
+ PKCS12 encryption is not secure and should not be used as a security
+ mechanism. Wrap a PKCS12 blob in a more secure envelope if you need
+ to store or send it safely. Encryption is provided for compatibility
+ reasons only.
+
+ Serialize a PKCS12 blob.
+
+ .. note::
+
+ Due to `a bug in Firefox`_ it's not possible to load unencrypted PKCS12
+ blobs in Firefox.
+
+ :param name: The friendly name to use for the supplied certificate and key.
+ :type name: bytes
+
+ :param key: The private key to include in the structure.
+ :type key: An
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization`
+ ,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`
+ , or
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`
+ object.
+
+ :param cert: The certificate associated with the private key.
+ :type cert: :class:`~cryptography.x509.Certificate` or ``None``
+
+ :param cas: An optional set of certificates to also include in the structure.
+ :type cas: list of :class:`~cryptography.x509.Certificate` or ``None``
+
+ :param encryption_algorithm: The encryption algorithm that should be used
+ for the key and certificate. An instance of an object conforming to the
+ :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
+ interface. PKCS12 encryption is **very weak** and should not be used
+ as a security boundary.
+
+ :return bytes: Serialized PKCS12.
+
+PKCS7
+~~~~~
+
+.. currentmodule:: cryptography.hazmat.primitives.serialization.pkcs7
+
+PKCS7 is a format described in :rfc:`2315`, among other specifications. It can
+contain certificates, CRLs, and much more. PKCS7 files commonly have a ``p7b``,
+``p7m``, or ``p7s`` file suffix but other suffixes are also seen in the wild.
+
+.. note::
+
+ ``cryptography`` only supports parsing certificates from PKCS7 files at
+ this time.
+
+.. function:: load_pem_pkcs7_certificates(data)
+
+ .. versionadded:: 3.1
+
+ Deserialize a PEM encoded PKCS7 blob to a list of certificates. PKCS7 can
+ contain many other types of data, including CRLs, but this function will
+ ignore everything except certificates.
+
+ :param data: The data.
+ :type data: bytes
+
+ :returns: A list of :class:`~cryptography.x509.Certificate`.
+
+ :raises ValueError: If the PKCS7 data could not be loaded.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the PKCS7 data
+ is of a type that is not supported.
+
+.. function:: load_der_pkcs7_certificates(data)
+
+ .. versionadded:: 3.1
+
+ Deserialize a DER encoded PKCS7 blob to a list of certificates. PKCS7 can
+ contain many other types of data, including CRLs, but this function will
+ ignore everything except certificates.
+
+ :param data: The data.
+ :type data: bytes
+
+ :returns: A list of :class:`~cryptography.x509.Certificate`.
+
+ :raises ValueError: If the PKCS7 data could not be loaded.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: If the PKCS7 data
+ is of a type that is not supported.
+
+.. testsetup::
+
+ ca_key = b"""
+ -----BEGIN PRIVATE KEY-----
+ MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgA8Zqz5vLeR0ePZUe
+ jBfdyMmnnI4U5uAJApWTsMn/RuWhRANCAAQY/8+7+Tm49d3D7sBAiwZ1BqtPzdgs
+ UiROH+AQRme1XxW5Yr07zwxvvhr3tKEPtLnLboazUPlsUb/Bgte+xfkF
+ -----END PRIVATE KEY-----
+ """.strip()
+
+ ca_cert = b"""
+ -----BEGIN CERTIFICATE-----
+ MIIBUTCB96ADAgECAgIDCTAKBggqhkjOPQQDAjAnMQswCQYDVQQGEwJVUzEYMBYG
+ A1UEAwwPY3J5cHRvZ3JhcGh5IENBMB4XDTE3MDEwMTEyMDEwMFoXDTM4MTIzMTA4
+ MzAwMFowJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD2NyeXB0b2dyYXBoeSBDQTBZ
+ MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBj/z7v5Obj13cPuwECLBnUGq0/N2CxS
+ JE4f4BBGZ7VfFblivTvPDG++Gve0oQ+0uctuhrNQ+WxRv8GC177F+QWjEzARMA8G
+ A1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhANES742XWm64tkGnz8Dn
+ pG6u2lHkZFQr3oaVvPcemvlbAiEA0WGGzmYx5C9UvfXIK7NEziT4pQtyESE0uRVK
+ Xw4nMqk=
+ -----END CERTIFICATE-----
+ """.strip()
+
+
+.. class:: PKCS7SignatureBuilder
+
+ The PKCS7 signature builder can create both basic PKCS7 signed messages as
+ well as S/MIME messages, which are commonly used in email. S/MIME has
+ multiple versions, but this implements a subset of :rfc:`2632`, also known
+ as S/MIME Version 3.
+
+ .. versionadded:: 3.2
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.primitives import hashes, serialization
+ >>> from cryptography.hazmat.primitives.serialization import pkcs7
+ >>> cert = x509.load_pem_x509_certificate(ca_cert)
+ >>> key = serialization.load_pem_private_key(ca_key, None)
+ >>> options = [pkcs7.PKCS7Options.DetachedSignature]
+ >>> pkcs7.PKCS7SignatureBuilder().set_data(
+ ... b"data to sign"
+ ... ).add_signer(
+ ... cert, key, hashes.SHA256()
+ ... ).sign(
+ ... serialization.Encoding.SMIME, options
+ ... )
+ b'...'
+
+ .. method:: set_data(data)
+
+ :param data: The data to be hashed and signed.
+ :type data: :term:`bytes-like`
+
+ .. method:: add_signer(certificate, private_key, hash_algorithm)
+
+ :param certificate: The :class:`~cryptography.x509.Certificate`.
+
+ :param private_key: The
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ associated with the certificate provided.
+
+ :param hash_algorithm: The
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
+ will be used to generate the signature. This must be an instance of
+ :class:`~cryptography.hazmat.primitives.hashes.SHA1`,
+ :class:`~cryptography.hazmat.primitives.hashes.SHA224`,
+ :class:`~cryptography.hazmat.primitives.hashes.SHA256`,
+ :class:`~cryptography.hazmat.primitives.hashes.SHA384`, or
+ :class:`~cryptography.hazmat.primitives.hashes.SHA512`.
+
+ .. method:: add_certificate(certificate)
+
+ Add an additional certificate (typically used to help build a
+ verification chain) to the PKCS7 structure. This method may
+ be called multiple times to add as many certificates as desired.
+
+ :param certificate: The :class:`~cryptography.x509.Certificate` to add.
+
+ .. method:: sign(encoding, options, backend=None)
+
+ :param encoding: :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`,
+ or :attr:`~cryptography.hazmat.primitives.serialization.Encoding.SMIME`.
+
+ :param options: A list of
+ :class:`~cryptography.hazmat.primitives.serialization.pkcs7.PKCS7Options`.
+
+ :return bytes: The signed PKCS7 message.
+
+ :param backend: An optional backend.
+
+
+.. class:: PKCS7Options
+
+ .. versionadded:: 3.2
+
+ An enumeration of options for PKCS7 signature creation.
+
+ .. attribute:: Text
+
+ The text option adds ``text/plain`` headers to an S/MIME message when
+ serializing to
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.SMIME`.
+ This option is disallowed with ``DER`` serialization.
+
+ .. attribute:: Binary
+
+ Signing normally converts line endings (LF to CRLF). When
+ passing this option the data will not be converted.
+
+ .. attribute:: DetachedSignature
+
+ Don't embed the signed data within the ASN.1. When signing with
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.SMIME`
+ this also results in the data being added as clear text before the
+ PEM encoded structure.
+
+ .. attribute:: NoCapabilities
+
+ PKCS7 structures contain a ``MIMECapabilities`` section inside the
+ ``authenticatedAttributes``. Passing this as an option removes
+ ``MIMECapabilities``.
+
+ .. attribute:: NoAttributes
+
+ PKCS7 structures contain an ``authenticatedAttributes`` section.
+ Passing this as an option removes that section. Note that if you
+ pass ``NoAttributes`` you can't pass ``NoCapabilities`` since
+ ``NoAttributes`` removes ``MIMECapabilities`` and more.
+
+ .. attribute:: NoCerts
+
+ Don't include the signer's certificate in the PKCS7 structure. This can
+ reduce the size of the signature but requires that the recipient can
+ obtain the signer's certificate by other means (for example from a
+ previously signed message).
+
Serialization Formats
~~~~~~~~~~~~~~~~~~~~~
@@ -486,6 +765,22 @@ Serialization Formats
A raw format used by :doc:`/hazmat/primitives/asymmetric/x448`. It is a
binary format and is invalid for other key types.
+ .. attribute:: OpenSSH
+
+ .. versionadded:: 3.0
+
+ Custom private key format for OpenSSH, internals are based on SSH protocol
+ and not ASN1. Requires
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`
+ encoding.
+
+ A PEM encoded OpenSSH key will look like::
+
+ -----BEGIN OPENSSH PRIVATE KEY-----
+ ...
+ -----END OPENSSH PRIVATE KEY-----
+
+
.. class:: PublicFormat
.. versionadded:: 0.8
@@ -615,6 +910,12 @@ Serialization Encodings
The format used by elliptic curve point encodings. This is a binary
format.
+ .. attribute:: SMIME
+
+ .. versionadded:: 3.2
+
+ An output format used for PKCS7. This is a text format.
+
Serialization Encryption Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -646,5 +947,8 @@ Serialization Encryption Types
Do not encrypt.
+.. _`a bug in Firefox`: https://bugzilla.mozilla.org/show_bug.cgi?id=773111
.. _`PKCS3`: https://www.teletrust.de/fileadmin/files/oid/oid_pkcs-3v1-4.pdf
-.. _`SEC 1 v2.0`: http://www.secg.org/sec1-v2.pdf
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
+.. _`PROTOCOL.key`: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
+.. _`PROTOCOL.certkeys`: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys
diff --git a/docs/hazmat/primitives/asymmetric/utils.rst b/docs/hazmat/primitives/asymmetric/utils.rst
index f46acb2ec..487926e91 100644
--- a/docs/hazmat/primitives/asymmetric/utils.rst
+++ b/docs/hazmat/primitives/asymmetric/utils.rst
@@ -57,7 +57,6 @@ Asymmetric Utilities
.. doctest::
>>> import hashlib
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import (
... padding, rsa, utils
@@ -65,7 +64,6 @@ Asymmetric Utilities
>>> private_key = rsa.generate_private_key(
... public_exponent=65537,
... key_size=2048,
- ... backend=default_backend()
... )
>>> prehashed_msg = hashlib.sha256(b"A message I want to sign").digest()
>>> signature = private_key.sign(
diff --git a/docs/hazmat/primitives/asymmetric/x25519.rst b/docs/hazmat/primitives/asymmetric/x25519.rst
index ea01fbaa0..014f3d01d 100644
--- a/docs/hazmat/primitives/asymmetric/x25519.rst
+++ b/docs/hazmat/primitives/asymmetric/x25519.rst
@@ -21,7 +21,6 @@ present.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
@@ -39,7 +38,6 @@ present.
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key)
>>> # For the next handshake we MUST generate another private key.
>>> private_key_2 = X25519PrivateKey.generate()
@@ -50,7 +48,6 @@ present.
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key_2)
Key interfaces
diff --git a/docs/hazmat/primitives/asymmetric/x448.rst b/docs/hazmat/primitives/asymmetric/x448.rst
index 4e1f0421f..f166355b8 100644
--- a/docs/hazmat/primitives/asymmetric/x448.rst
+++ b/docs/hazmat/primitives/asymmetric/x448.rst
@@ -21,7 +21,6 @@ present.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric.x448 import X448PrivateKey
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
@@ -39,7 +38,6 @@ present.
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key)
>>> # For the next handshake we MUST generate another private key.
>>> private_key_2 = X448PrivateKey.generate()
@@ -50,7 +48,6 @@ present.
... length=32,
... salt=None,
... info=b'handshake data',
- ... backend=default_backend()
... ).derive(shared_key_2)
Key interfaces
diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst
index 24cc70b5e..4cdc034a6 100644
--- a/docs/hazmat/primitives/cryptographic-hashes.rst
+++ b/docs/hazmat/primitives/cryptographic-hashes.rst
@@ -5,7 +5,7 @@ Message digests (Hashing)
.. module:: cryptography.hazmat.primitives.hashes
-.. class:: Hash(algorithm, backend)
+.. class:: Hash(algorithm, backend=None)
A cryptographic hash function takes an arbitrary block of data and
calculates a fixed-size bit string (a digest), such that different data
@@ -20,9 +20,8 @@ Message digests (Hashing)
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
- >>> digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
+ >>> digest = hashes.Hash(hashes.SHA256())
>>> digest.update(b"abc")
>>> digest.update(b"123")
>>> digest.finalize()
@@ -42,7 +41,7 @@ Message digests (Hashing)
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
instance such as those described in
:ref:`below <cryptographic-hash-algorithms>`.
- :param backend: A
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.HashBackend`
instance.
diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst
index be03b19cb..62457b284 100644
--- a/docs/hazmat/primitives/key-derivation-functions.rst
+++ b/docs/hazmat/primitives/key-derivation-functions.rst
@@ -26,9 +26,17 @@ Different KDFs are suitable for different tasks such as:
Ideal password storage KDFs will be demanding on both computational and
memory resources.
+
+Variable cost algorithms
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+PBKDF2
+------
+
.. currentmodule:: cryptography.hazmat.primitives.kdf.pbkdf2
-.. class:: PBKDF2HMAC(algorithm, length, salt, iterations, backend)
+.. class:: PBKDF2HMAC(algorithm, length, salt, iterations, backend=None)
.. versionadded:: 0.2
@@ -47,8 +55,6 @@ Different KDFs are suitable for different tasks such as:
>>> import os
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
>>> # Salts should be randomly generated
>>> salt = os.urandom(16)
>>> # derive
@@ -57,7 +63,6 @@ Different KDFs are suitable for different tasks such as:
... length=32,
... salt=salt,
... iterations=100000,
- ... backend=backend
... )
>>> key = kdf.derive(b"my great password")
>>> # verify
@@ -66,7 +71,6 @@ Different KDFs are suitable for different tasks such as:
... length=32,
... salt=salt,
... iterations=100000,
- ... backend=backend
... )
>>> kdf.verify(b"my great password", key)
@@ -79,9 +83,9 @@ Different KDFs are suitable for different tasks such as:
:param int iterations: The number of iterations to perform of the hash
function. This can be used to control the length of time the operation
takes. Higher numbers help mitigate brute force attacks against derived
- keys. See OWASP's `Password Storage Cheat Sheet`_ for more
- detailed recommendations if you intend to use this for password storage.
- :param backend: An instance of
+ keys. A `more detailed description`_ can be consulted for additional
+ information.
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.PBKDF2HMACBackend`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
@@ -130,172 +134,91 @@ Different KDFs are suitable for different tasks such as:
key.
-.. currentmodule:: cryptography.hazmat.primitives.kdf.hkdf
+Scrypt
+------
-.. class:: HKDF(algorithm, length, salt, info, backend)
+.. currentmodule:: cryptography.hazmat.primitives.kdf.scrypt
- .. versionadded:: 0.2
+.. class:: Scrypt(salt, length, n, r, p, backend=None)
- `HKDF`_ (HMAC-based Extract-and-Expand Key Derivation Function) is suitable
- for deriving keys of a fixed size used for other cryptographic operations.
+ .. versionadded:: 1.6
- .. warning::
+ Scrypt is a KDF designed for password storage by Colin Percival to be
+ resistant against hardware-assisted attackers by having a tunable memory
+ cost. It is described in :rfc:`7914`.
- HKDF should not be used for password storage.
+ This class conforms to the
+ :class:`~cryptography.hazmat.primitives.kdf.KeyDerivationFunction`
+ interface.
.. doctest::
>>> import os
- >>> from cryptography.hazmat.primitives import hashes
- >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
+ >>> from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
>>> salt = os.urandom(16)
- >>> info = b"hkdf-example"
- >>> hkdf = HKDF(
- ... algorithm=hashes.SHA256(),
- ... length=32,
+ >>> # derive
+ >>> kdf = Scrypt(
... salt=salt,
- ... info=info,
- ... backend=backend
- ... )
- >>> key = hkdf.derive(b"input key")
- >>> hkdf = HKDF(
- ... algorithm=hashes.SHA256(),
... length=32,
+ ... n=2**14,
+ ... r=8,
+ ... p=1,
+ ... )
+ >>> key = kdf.derive(b"my great password")
+ >>> # verify
+ >>> kdf = Scrypt(
... salt=salt,
- ... info=info,
- ... backend=backend
+ ... length=32,
+ ... n=2**14,
+ ... r=8,
+ ... p=1,
... )
- >>> hkdf.verify(b"input key", key)
-
- :param algorithm: An instance of
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
-
- :param int length: The desired length of the derived key in bytes. Maximum
- is ``255 * (algorithm.digest_size // 8)``.
+ >>> kdf.verify(b"my great password", key)
- :param bytes salt: A salt. Randomizes the KDF's output. Optional, but
- highly recommended. Ideally as many bits of entropy as the security
- level of the hash: often that means cryptographically random and as
- long as the hash output. Worse (shorter, less entropy) salt values can
- still meaningfully contribute to security. May be reused. Does not have
- to be secret, but may cause stronger security guarantees if secret; see
- :rfc:`5869` and the `HKDF paper`_ for more details. If ``None`` is
- explicitly passed a default salt of ``algorithm.digest_size // 8`` null
- bytes will be used.
+ :param bytes salt: A salt.
+ :param int length: The desired length of the derived key in bytes.
+ :param int n: CPU/Memory cost parameter. It must be larger than 1 and be a
+ power of 2.
+ :param int r: Block size parameter.
+ :param int p: Parallelization parameter.
+ :param backend: An optional instance of
+ :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`.
- :param bytes info: Application specific context information. If ``None``
- is explicitly passed an empty byte string will be used.
+ The computational and memory cost of Scrypt can be adjusted by manipulating
+ the 3 parameters: ``n``, ``r``, and ``p``. In general, the memory cost of
+ Scrypt is affected by the values of both ``n`` and ``r``, while ``n`` also
+ determines the number of iterations performed. ``p`` increases the
+ computational cost without affecting memory usage. A more in-depth
+ explanation of the 3 parameters can be found `here`_.
- :param backend: An instance of
- :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
+ :rfc:`7914` `recommends`_ values of ``r=8`` and ``p=1`` while scaling ``n``
+ to a number appropriate for your system. `The scrypt paper`_ suggests a
+ minimum value of ``n=2**14`` for interactive logins (t < 100ms), or
+ ``n=2**20`` for more sensitive files (t < 5s).
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
provided ``backend`` does not implement
- :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+ :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`
- :raises TypeError: This exception is raised if ``salt`` or ``info`` is not
- ``bytes``.
+ :raises TypeError: This exception is raised if ``salt`` is not ``bytes``.
+ :raises ValueError: This exception is raised if ``n`` is less than 2, if
+ ``n`` is not a power of 2, if ``r`` is less than 1 or if ``p`` is less
+ than 1.
.. method:: derive(key_material)
:param key_material: The input key material.
:type key_material: :term:`bytes-like`
- :return bytes: The derived key.
+ :return bytes: the derived key.
:raises TypeError: This exception is raised if ``key_material`` is not
``bytes``.
-
- Derives a new key from the input key material by performing both the
- extract and expand operations.
-
- .. method:: verify(key_material, expected_key)
-
- :param bytes key_material: The input key material. This is the same as
- ``key_material`` in :meth:`derive`.
- :param bytes expected_key: The expected result of deriving a new key,
- this is the same as the return value of
- :meth:`derive`.
- :raises cryptography.exceptions.InvalidKey: This is raised when the
- derived key does not match
- the expected key.
:raises cryptography.exceptions.AlreadyFinalized: This is raised when
:meth:`derive` or
:meth:`verify` is
called more than
once.
- This checks whether deriving a new key from the supplied
- ``key_material`` generates the same key as the ``expected_key``, and
- raises an exception if they do not match.
-
-
-.. class:: HKDFExpand(algorithm, length, info, backend)
-
- .. versionadded:: 0.5
-
- HKDF consists of two stages, extract and expand. This class exposes an
- expand only version of HKDF that is suitable when the key material is
- already cryptographically strong.
-
- .. warning::
-
- HKDFExpand should only be used if the key material is
- cryptographically strong. You should use
- :class:`~cryptography.hazmat.primitives.kdf.hkdf.HKDF` if
- you are unsure.
-
- .. doctest::
-
- >>> import os
- >>> from cryptography.hazmat.primitives import hashes
- >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDFExpand
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
- >>> info = b"hkdf-example"
- >>> key_material = os.urandom(16)
- >>> hkdf = HKDFExpand(
- ... algorithm=hashes.SHA256(),
- ... length=32,
- ... info=info,
- ... backend=backend
- ... )
- >>> key = hkdf.derive(key_material)
- >>> hkdf = HKDFExpand(
- ... algorithm=hashes.SHA256(),
- ... length=32,
- ... info=info,
- ... backend=backend
- ... )
- >>> hkdf.verify(key_material, key)
-
- :param algorithm: An instance of
- :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
-
- :param int length: The desired length of the derived key in bytes. Maximum
- is ``255 * (algorithm.digest_size // 8)``.
-
- :param bytes info: Application specific context information. If ``None``
- is explicitly passed an empty byte string will be used.
-
- :param backend: An instance of
- :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
-
- :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
- provided ``backend`` does not implement
- :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
- :raises TypeError: This exception is raised if ``info`` is not ``bytes``.
-
- .. method:: derive(key_material)
-
- :param bytes key_material: The input key material.
- :return bytes: The derived key.
-
- :raises TypeError: This exception is raised if ``key_material`` is not
- ``bytes``.
-
- Derives a new key from the input key material by performing both the
- extract and expand operations.
+ This generates and returns a new key from the supplied password.
.. method:: verify(key_material, expected_key)
@@ -312,16 +235,23 @@ Different KDFs are suitable for different tasks such as:
:meth:`verify` is
called more than
once.
- :raises TypeError: This is raised if the provided ``key_material`` is
- a ``unicode`` object
This checks whether deriving a new key from the supplied
``key_material`` generates the same key as the ``expected_key``, and
- raises an exception if they do not match.
+ raises an exception if they do not match. This can be used for
+ checking whether the password a user provides matches the stored derived
+ key.
+
+Fixed cost algorithms
+~~~~~~~~~~~~~~~~~~~~~
+
+
+ConcatKDF
+---------
.. currentmodule:: cryptography.hazmat.primitives.kdf.concatkdf
-.. class:: ConcatKDFHash(algorithm, length, otherinfo, backend)
+.. class:: ConcatKDFHash(algorithm, length, otherinfo, backend=None)
.. versionadded:: 1.0
@@ -338,21 +268,17 @@ Different KDFs are suitable for different tasks such as:
>>> import os
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
>>> otherinfo = b"concatkdf-example"
>>> ckdf = ConcatKDFHash(
... algorithm=hashes.SHA256(),
... length=32,
... otherinfo=otherinfo,
- ... backend=backend
... )
>>> key = ckdf.derive(b"input key")
>>> ckdf = ConcatKDFHash(
... algorithm=hashes.SHA256(),
... length=32,
... otherinfo=otherinfo,
- ... backend=backend
... )
>>> ckdf.verify(b"input key", key)
@@ -365,7 +291,7 @@ Different KDFs are suitable for different tasks such as:
:param bytes otherinfo: Application specific context information.
If ``None`` is explicitly passed an empty byte string will be used.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.HashBackend`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
@@ -382,6 +308,11 @@ Different KDFs are suitable for different tasks such as:
:return bytes: The derived key.
:raises TypeError: This exception is raised if ``key_material`` is
not ``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
Derives a new key from the input key material.
@@ -406,7 +337,7 @@ Different KDFs are suitable for different tasks such as:
raises an exception if they do not match.
-.. class:: ConcatKDFHMAC(algorithm, length, salt, otherinfo, backend)
+.. class:: ConcatKDFHMAC(algorithm, length, salt, otherinfo, backend=None)
.. versionadded:: 1.0
@@ -421,8 +352,6 @@ Different KDFs are suitable for different tasks such as:
>>> import os
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHMAC
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
>>> salt = os.urandom(16)
>>> otherinfo = b"concatkdf-example"
>>> ckdf = ConcatKDFHMAC(
@@ -430,7 +359,6 @@ Different KDFs are suitable for different tasks such as:
... length=32,
... salt=salt,
... otherinfo=otherinfo,
- ... backend=backend
... )
>>> key = ckdf.derive(b"input key")
>>> ckdf = ConcatKDFHMAC(
@@ -438,7 +366,6 @@ Different KDFs are suitable for different tasks such as:
... length=32,
... salt=salt,
... otherinfo=otherinfo,
- ... backend=backend
... )
>>> ckdf.verify(b"input key", key)
@@ -459,7 +386,7 @@ Different KDFs are suitable for different tasks such as:
:param bytes otherinfo: Application specific context information.
If ``None`` is explicitly passed an empty byte string will be used.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
@@ -475,6 +402,11 @@ Different KDFs are suitable for different tasks such as:
:return bytes: The derived key.
:raises TypeError: This exception is raised if ``key_material`` is not
``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
Derives a new key from the input key material.
@@ -498,78 +430,178 @@ Different KDFs are suitable for different tasks such as:
``key_material`` generates the same key as the ``expected_key``, and
raises an exception if they do not match.
-.. currentmodule:: cryptography.hazmat.primitives.kdf.x963kdf
-.. class:: X963KDF(algorithm, length, otherinfo, backend)
+HKDF
+----
- .. versionadded:: 1.1
+.. currentmodule:: cryptography.hazmat.primitives.kdf.hkdf
- X963KDF (ANSI X9.63 Key Derivation Function) is defined by ANSI
- in the `ANSI X9.63:2001`_ document, to be used to derive keys for use
- after a Key Exchange negotiation operation.
+.. class:: HKDF(algorithm, length, salt, info, backend=None)
- SECG in `SEC 1 v2.0`_ recommends that
- :class:`~cryptography.hazmat.primitives.kdf.concatkdf.ConcatKDFHash` be
- used for new projects. This KDF should only be used for backwards
- compatibility with pre-existing protocols.
+ .. versionadded:: 0.2
+ `HKDF`_ (HMAC-based Extract-and-Expand Key Derivation Function) is suitable
+ for deriving keys of a fixed size used for other cryptographic operations.
.. warning::
- X963KDF should not be used for password storage.
+ HKDF should not be used for password storage.
.. doctest::
>>> import os
>>> from cryptography.hazmat.primitives import hashes
- >>> from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
- >>> sharedinfo = b"ANSI X9.63 Example"
- >>> xkdf = X963KDF(
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+ >>> salt = os.urandom(16)
+ >>> info = b"hkdf-example"
+ >>> hkdf = HKDF(
... algorithm=hashes.SHA256(),
... length=32,
- ... sharedinfo=sharedinfo,
- ... backend=backend
+ ... salt=salt,
+ ... info=info,
... )
- >>> key = xkdf.derive(b"input key")
- >>> xkdf = X963KDF(
+ >>> key = hkdf.derive(b"input key")
+ >>> hkdf = HKDF(
... algorithm=hashes.SHA256(),
... length=32,
- ... sharedinfo=sharedinfo,
- ... backend=backend
+ ... salt=salt,
+ ... info=info,
... )
- >>> xkdf.verify(b"input key", key)
+ >>> hkdf.verify(b"input key", key)
:param algorithm: An instance of
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
- :param int length: The desired length of the derived key in bytes.
- Maximum is ``hashlen * (2^32 -1)``.
+ :param int length: The desired length of the derived key in bytes. Maximum
+ is ``255 * (algorithm.digest_size // 8)``.
- :param bytes sharedinfo: Application specific context information.
- If ``None`` is explicitly passed an empty byte string will be used.
+ :param bytes salt: A salt. Randomizes the KDF's output. Optional, but
+ highly recommended. Ideally as many bits of entropy as the security
+ level of the hash: often that means cryptographically random and as
+ long as the hash output. Worse (shorter, less entropy) salt values can
+ still meaningfully contribute to security. May be reused. Does not have
+ to be secret, but may cause stronger security guarantees if secret; see
+ :rfc:`5869` and the `HKDF paper`_ for more details. If ``None`` is
+ explicitly passed a default salt of ``algorithm.digest_size // 8`` null
+ bytes will be used.
- :param backend: A cryptography backend
- :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
- instance.
+ :param bytes info: Application specific context information. If ``None``
+ is explicitly passed an empty byte string will be used.
- :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
- if the provided ``backend`` does not implement
- :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
+ :param backend: An optional instance of
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
- :raises TypeError: This exception is raised if ``sharedinfo`` is not
- ``bytes``.
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
+ provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+
+ :raises TypeError: This exception is raised if ``salt`` or ``info`` is not
+ ``bytes``.
.. method:: derive(key_material)
:param key_material: The input key material.
:type key_material: :term:`bytes-like`
:return bytes: The derived key.
- :raises TypeError: This exception is raised if ``key_material`` is
- not ``bytes``.
+ :raises TypeError: This exception is raised if ``key_material`` is not
+ ``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
- Derives a new key from the input key material.
+ Derives a new key from the input key material by performing both the
+ extract and expand operations.
+
+ .. method:: verify(key_material, expected_key)
+
+ :param bytes key_material: The input key material. This is the same as
+ ``key_material`` in :meth:`derive`.
+ :param bytes expected_key: The expected result of deriving a new key,
+ this is the same as the return value of
+ :meth:`derive`.
+ :raises cryptography.exceptions.InvalidKey: This is raised when the
+ derived key does not match
+ the expected key.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
+
+ This checks whether deriving a new key from the supplied
+ ``key_material`` generates the same key as the ``expected_key``, and
+ raises an exception if they do not match.
+
+
+.. class:: HKDFExpand(algorithm, length, info, backend=None)
+
+ .. versionadded:: 0.5
+
+ HKDF consists of two stages, extract and expand. This class exposes an
+ expand only version of HKDF that is suitable when the key material is
+ already cryptographically strong.
+
+ .. warning::
+
+ HKDFExpand should only be used if the key material is
+ cryptographically strong. You should use
+ :class:`~cryptography.hazmat.primitives.kdf.hkdf.HKDF` if
+ you are unsure.
+
+ .. doctest::
+
+ >>> import os
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.kdf.hkdf import HKDFExpand
+ >>> info = b"hkdf-example"
+ >>> key_material = os.urandom(16)
+ >>> hkdf = HKDFExpand(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... info=info,
+ ... )
+ >>> key = hkdf.derive(key_material)
+ >>> hkdf = HKDFExpand(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... info=info,
+ ... )
+ >>> hkdf.verify(key_material, key)
+
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
+
+ :param int length: The desired length of the derived key in bytes. Maximum
+ is ``255 * (algorithm.digest_size // 8)``.
+
+ :param bytes info: Application specific context information. If ``None``
+ is explicitly passed an empty byte string will be used.
+
+ :param backend: An optional instance of
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
+ provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+ :raises TypeError: This exception is raised if ``info`` is not ``bytes``.
+
+ .. method:: derive(key_material)
+
+ :param bytes key_material: The input key material.
+ :return bytes: The derived key.
+
+ :raises TypeError: This exception is raised if ``key_material`` is not
+ ``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
+
+ Derives a new key from the input key material by performing both the
+ extract and expand operations.
.. method:: verify(key_material, expected_key)
@@ -586,16 +618,21 @@ Different KDFs are suitable for different tasks such as:
:meth:`verify` is
called more than
once.
+ :raises TypeError: This is raised if the provided ``key_material`` is
+ a ``unicode`` object
This checks whether deriving a new key from the supplied
``key_material`` generates the same key as the ``expected_key``, and
raises an exception if they do not match.
+KBKDF
+-----
+
.. currentmodule:: cryptography.hazmat.primitives.kdf.kbkdf
.. class:: KBKDFHMAC(algorithm, mode, length, rlen, llen, location,\
- label, context, fixed, backend)
+ label, context, fixed, backend=None)
.. versionadded:: 1.4
@@ -615,8 +652,6 @@ Different KDFs are suitable for different tasks such as:
>>> from cryptography.hazmat.primitives.kdf.kbkdf import (
... CounterLocation, KBKDFHMAC, Mode
... )
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
>>> label = b"KBKDF HMAC Label"
>>> context = b"KBKDF HMAC Context"
>>> kdf = KBKDFHMAC(
@@ -629,7 +664,6 @@ Different KDFs are suitable for different tasks such as:
... label=label,
... context=context,
... fixed=None,
- ... backend=backend
... )
>>> key = kdf.derive(b"input key")
>>> kdf = KBKDFHMAC(
@@ -642,7 +676,6 @@ Different KDFs are suitable for different tasks such as:
... label=label,
... context=context,
... fixed=None,
- ... backend=backend
... )
>>> kdf.verify(b"input key", key)
@@ -673,13 +706,12 @@ Different KDFs are suitable for different tasks such as:
may supply your own fixed data. If ``fixed`` is specified, ``label``
and ``context`` is ignored.
- :param backend: A cryptography backend
- :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
- instance.
+ :param backend: An optional instance of
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
if the provided ``backend`` does not implement
- :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
:raises TypeError: This exception is raised if ``label`` or ``context``
is not ``bytes``. Also raised if ``rlen`` or ``llen`` is not ``int``.
@@ -695,6 +727,11 @@ Different KDFs are suitable for different tasks such as:
:return bytes: The derived key.
:raises TypeError: This exception is raised if ``key_material`` is
not ``bytes``.
+ :raises cryptography.exceptions.AlreadyFinalized: This is raised when
+ :meth:`derive` or
+ :meth:`verify` is
+ called more than
+ once.
Derives a new key from the input key material.
@@ -741,93 +778,82 @@ Different KDFs are suitable for different tasks such as:
The counter iteration variable will be concatenated after
the fixed input data.
-.. currentmodule:: cryptography.hazmat.primitives.kdf.scrypt
-.. class:: Scrypt(salt, length, n, r, p, backend)
+X963KDF
+-------
- .. versionadded:: 1.6
+.. currentmodule:: cryptography.hazmat.primitives.kdf.x963kdf
- Scrypt is a KDF designed for password storage by Colin Percival to be
- resistant against hardware-assisted attackers by having a tunable memory
- cost. It is described in :rfc:`7914`.
+.. class:: X963KDF(algorithm, length, otherinfo, backend=None)
- This class conforms to the
- :class:`~cryptography.hazmat.primitives.kdf.KeyDerivationFunction`
- interface.
+ .. versionadded:: 1.1
+
+ X963KDF (ANSI X9.63 Key Derivation Function) is defined by ANSI
+ in the `ANSI X9.63:2001`_ document, to be used to derive keys for use
+ after a Key Exchange negotiation operation.
+
+ SECG in `SEC 1 v2.0`_ recommends that
+ :class:`~cryptography.hazmat.primitives.kdf.concatkdf.ConcatKDFHash` be
+ used for new projects. This KDF should only be used for backwards
+ compatibility with pre-existing protocols.
+
+
+ .. warning::
+
+ X963KDF should not be used for password storage.
.. doctest::
>>> import os
- >>> from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
- >>> salt = os.urandom(16)
- >>> # derive
- >>> kdf = Scrypt(
- ... salt=salt,
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
+ >>> sharedinfo = b"ANSI X9.63 Example"
+ >>> xkdf = X963KDF(
+ ... algorithm=hashes.SHA256(),
... length=32,
- ... n=2**14,
- ... r=8,
- ... p=1,
- ... backend=backend
+ ... sharedinfo=sharedinfo,
... )
- >>> key = kdf.derive(b"my great password")
- >>> # verify
- >>> kdf = Scrypt(
- ... salt=salt,
+ >>> key = xkdf.derive(b"input key")
+ >>> xkdf = X963KDF(
+ ... algorithm=hashes.SHA256(),
... length=32,
- ... n=2**14,
- ... r=8,
- ... p=1,
- ... backend=backend
+ ... sharedinfo=sharedinfo,
... )
- >>> kdf.verify(b"my great password", key)
+ >>> xkdf.verify(b"input key", key)
- :param bytes salt: A salt.
- :param int length: The desired length of the derived key in bytes.
- :param int n: CPU/Memory cost parameter. It must be larger than 1 and be a
- power of 2.
- :param int r: Block size parameter.
- :param int p: Parallelization parameter.
+ :param algorithm: An instance of
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`.
- The computational and memory cost of Scrypt can be adjusted by manipulating
- the 3 parameters: ``n``, ``r``, and ``p``. In general, the memory cost of
- Scrypt is affected by the values of both ``n`` and ``r``, while ``n`` also
- determines the number of iterations performed. ``p`` increases the
- computational cost without affecting memory usage. A more in-depth
- explanation of the 3 parameters can be found `here`_.
+ :param int length: The desired length of the derived key in bytes.
+ Maximum is ``hashlen * (2^32 -1)``.
- :rfc:`7914` `recommends`_ values of ``r=8`` and ``p=1`` while scaling ``n``
- to a number appropriate for your system. `The scrypt paper`_ suggests a
- minimum value of ``n=2**14`` for interactive logins (t < 100ms), or
- ``n=2**20`` for more sensitive files (t < 5s).
+ :param bytes sharedinfo: Application specific context information.
+ If ``None`` is explicitly passed an empty byte string will be used.
- :param backend: An instance of
- :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`.
+ :param backend: An optional instance of
+ :class:`~cryptography.hazmat.backends.interfaces.HashBackend`.
- :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
- provided ``backend`` does not implement
- :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised
+ if the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
- :raises TypeError: This exception is raised if ``salt`` is not ``bytes``.
- :raises ValueError: This exception is raised if ``n`` is less than 2, if
- ``n`` is not a power of 2, if ``r`` is less than 1 or if ``p`` is less
- than 1.
+ :raises TypeError: This exception is raised if ``sharedinfo`` is not
+ ``bytes``.
.. method:: derive(key_material)
:param key_material: The input key material.
:type key_material: :term:`bytes-like`
- :return bytes: the derived key.
- :raises TypeError: This exception is raised if ``key_material`` is not
- ``bytes``.
+ :return bytes: The derived key.
+ :raises TypeError: This exception is raised if ``key_material`` is
+ not ``bytes``.
:raises cryptography.exceptions.AlreadyFinalized: This is raised when
:meth:`derive` or
:meth:`verify` is
called more than
once.
- This generates and returns a new key from the supplied password.
+ Derives a new key from the input key material.
.. method:: verify(key_material, expected_key)
@@ -847,9 +873,8 @@ Different KDFs are suitable for different tasks such as:
This checks whether deriving a new key from the supplied
``key_material`` generates the same key as the ``expected_key``, and
- raises an exception if they do not match. This can be used for
- checking whether the password a user provides matches the stored derived
- key.
+ raises an exception if they do not match.
+
Interface
~~~~~~~~~
@@ -904,8 +929,8 @@ Interface
.. _`NIST SP 800-108`: https://csrc.nist.gov/publications/detail/sp/800-108/final
.. _`NIST SP 800-56Ar2`: https://csrc.nist.gov/publications/detail/sp/800-56a/rev-2/final
.. _`ANSI X9.63:2001`: https://webstore.ansi.org
-.. _`SEC 1 v2.0`: http://www.secg.org/sec1-v2.pdf
-.. _`Password Storage Cheat Sheet`: https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
+.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf
+.. _`more detailed description`: https://security.stackexchange.com/a/3993/43116
.. _`PBKDF2`: https://en.wikipedia.org/wiki/PBKDF2
.. _`key stretching`: https://en.wikipedia.org/wiki/Key_stretching
.. _`HKDF`: https://en.wikipedia.org/wiki/HKDF
diff --git a/docs/hazmat/primitives/keywrap.rst b/docs/hazmat/primitives/keywrap.rst
index 1c15f9d19..9d8abbd09 100644
--- a/docs/hazmat/primitives/keywrap.rst
+++ b/docs/hazmat/primitives/keywrap.rst
@@ -11,7 +11,7 @@ to protect keys at rest or transmit them over insecure networks. Many of the
protections offered by key wrapping are also offered by using authenticated
:doc:`symmetric encryption </hazmat/primitives/symmetric-encryption>`.
-.. function:: aes_key_wrap(wrapping_key, key_to_wrap, backend)
+.. function:: aes_key_wrap(wrapping_key, key_to_wrap, backend=None)
.. versionadded:: 1.1
@@ -22,14 +22,14 @@ protections offered by key wrapping are also offered by using authenticated
:param bytes key_to_wrap: The key to wrap.
- :param backend: A
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
instance that supports
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
:return bytes: The wrapped key as bytes.
-.. function:: aes_key_unwrap(wrapping_key, wrapped_key, backend)
+.. function:: aes_key_unwrap(wrapping_key, wrapped_key, backend=None)
.. versionadded:: 1.1
@@ -40,7 +40,7 @@ protections offered by key wrapping are also offered by using authenticated
:param bytes wrapped_key: The wrapped key.
- :param backend: A
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
instance that supports
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
@@ -50,7 +50,7 @@ protections offered by key wrapping are also offered by using authenticated
:raises cryptography.hazmat.primitives.keywrap.InvalidUnwrap: This is
raised if the key is not successfully unwrapped.
-.. function:: aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend)
+.. function:: aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend=None)
.. versionadded:: 2.2
@@ -61,14 +61,14 @@ protections offered by key wrapping are also offered by using authenticated
:param bytes key_to_wrap: The key to wrap.
- :param backend: A
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
instance that supports
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
:return bytes: The wrapped key as bytes.
-.. function:: aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend)
+.. function:: aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend=None)
.. versionadded:: 2.2
@@ -79,7 +79,7 @@ protections offered by key wrapping are also offered by using authenticated
:param bytes wrapped_key: The wrapped key.
- :param backend: A
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
instance that supports
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
diff --git a/docs/hazmat/primitives/mac/cmac.rst b/docs/hazmat/primitives/mac/cmac.rst
index a5b13caf7..b40a90a82 100644
--- a/docs/hazmat/primitives/mac/cmac.rst
+++ b/docs/hazmat/primitives/mac/cmac.rst
@@ -17,7 +17,7 @@ of a message.
A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`.
-.. class:: CMAC(algorithm, backend)
+.. class:: CMAC(algorithm, backend=None)
.. versionadded:: 0.4
@@ -26,10 +26,9 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import cmac
>>> from cryptography.hazmat.primitives.ciphers import algorithms
- >>> c = cmac.CMAC(algorithms.AES(key), backend=default_backend())
+ >>> c = cmac.CMAC(algorithms.AES(key))
>>> c.update(b"message to authenticate")
>>> c.finalize()
b'CT\x1d\xc8\x0e\x15\xbe4e\xdb\xb6\x84\xca\xd9Xk'
@@ -47,7 +46,7 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`.
.. doctest::
- >>> c = cmac.CMAC(algorithms.AES(key), backend=default_backend())
+ >>> c = cmac.CMAC(algorithms.AES(key))
>>> c.update(b"message to authenticate")
>>> c.verify(b"an incorrect signature")
Traceback (most recent call last):
@@ -56,7 +55,7 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`.
:param algorithm: An instance of
:class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`.
- :param backend: An instance of
+ :param backend: An optional instance of
:class:`~cryptography.hazmat.backends.interfaces.CMACBackend`.
:raises TypeError: This is raised if the provided ``algorithm`` is not an instance of
:class:`~cryptography.hazmat.primitives.ciphers.BlockCipherAlgorithm`
diff --git a/docs/hazmat/primitives/mac/hmac.rst b/docs/hazmat/primitives/mac/hmac.rst
index 9d11694bd..3695270b7 100644
--- a/docs/hazmat/primitives/mac/hmac.rst
+++ b/docs/hazmat/primitives/mac/hmac.rst
@@ -15,7 +15,7 @@ message authentication codes using a cryptographic hash function coupled with a
secret key. You can use an HMAC to verify both the integrity and authenticity
of a message.
-.. class:: HMAC(key, algorithm, backend)
+.. class:: HMAC(key, algorithm, backend=None)
HMAC objects take a ``key`` and a
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` instance.
@@ -27,9 +27,8 @@ of a message.
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes, hmac
- >>> h = hmac.HMAC(key, hashes.SHA256(), backend=default_backend())
+ >>> h = hmac.HMAC(key, hashes.SHA256())
>>> h.update(b"message to hash")
>>> h.finalize()
b'#F\xdaI\x8b"e\xc4\xf1\xbb\x9a\x8fc\xff\xf5\xdex.\xbc\xcd/+\x8a\x86\x1d\x84\'\xc3\xa6\x1d\xd8J'
@@ -47,7 +46,7 @@ of a message.
.. doctest::
- >>> h = hmac.HMAC(key, hashes.SHA256(), backend=default_backend())
+ >>> h = hmac.HMAC(key, hashes.SHA256())
>>> h.update(b"message to hash")
>>> h.verify(b"an incorrect signature")
Traceback (most recent call last):
@@ -60,7 +59,7 @@ of a message.
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
instance such as those described in
:ref:`Cryptographic Hashes <cryptographic-hash-algorithms>`.
- :param backend: An
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
instance.
diff --git a/docs/hazmat/primitives/mac/index.rst b/docs/hazmat/primitives/mac/index.rst
index 86c407c43..8bfe29e30 100644
--- a/docs/hazmat/primitives/mac/index.rst
+++ b/docs/hazmat/primitives/mac/index.rst
@@ -3,48 +3,17 @@
Message authentication codes
============================
-While cryptography supports both the CMAC and HMAC algorithms, we strongly
-recommend that HMAC should be used unless you have a good reason otherwise.
+While cryptography supports multiple MAC algorithms, we strongly
+recommend that HMAC should be used unless you have a very specific need.
For more information on why HMAC is preferred, see `Use cases for CMAC vs.
HMAC?`_
-HMAC and CMAC both use the ``MACContext`` interface:
-
-.. currentmodule:: cryptography.hazmat.primitives.mac
-
-.. class:: MACContext
-
- .. versionadded:: 0.7
-
- .. method:: update(data)
-
- :param bytes data: The data you want to authenticate.
-
- .. method:: finalize()
-
- :return: The message authentication code.
-
- .. method:: copy()
-
- :return: A
- :class:`~cryptography.hazmat.primitives.mac.MACContext` that
- is a copy of the current context.
-
- .. method:: verify(signature)
-
- :param bytes signature: The signature to verify.
-
- :raises cryptography.exceptions.InvalidSignature: This is raised when
- the provided signature does not match the expected signature.
-
-
-
-.. _`CMAC`: https://en.wikipedia.org/wiki/CMAC
-.. _`Use cases for CMAC vs. HMAC?`: https://crypto.stackexchange.com/questions/15721/use-cases-for-cmac-vs-hmac
-
.. toctree::
:maxdepth: 1
cmac
hmac
+ poly1305
+
+.. _`Use cases for CMAC vs. HMAC?`: https://crypto.stackexchange.com/questions/15721/use-cases-for-cmac-vs-hmac
diff --git a/docs/hazmat/primitives/mac/poly1305.rst b/docs/hazmat/primitives/mac/poly1305.rst
new file mode 100644
index 000000000..7504a076e
--- /dev/null
+++ b/docs/hazmat/primitives/mac/poly1305.rst
@@ -0,0 +1,132 @@
+.. hazmat::
+
+Poly1305
+========
+
+.. currentmodule:: cryptography.hazmat.primitives.poly1305
+
+.. testsetup::
+
+ key = b"\x01" * 32
+
+Poly1305 is an authenticator that takes a 32-byte key and a message and
+produces a 16-byte tag. This tag is used to authenticate the message. Each key
+**must** only be used once. Using the same key to generate tags for multiple
+messages allows an attacker to forge tags. Poly1305 is described in
+:rfc:`7539`.
+
+.. class:: Poly1305(key)
+
+ .. versionadded:: 2.7
+
+ .. warning::
+
+ Using the same key to generate tags for multiple messages allows an
+ attacker to forge tags. Always generate a new key per message you want
+ to authenticate. If you are using this as a MAC for
+ symmetric encryption please use
+ :class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305`
+ instead.
+
+ .. doctest::
+
+ >>> from cryptography.hazmat.primitives import poly1305
+ >>> p = poly1305.Poly1305(key)
+ >>> p.update(b"message to authenticate")
+ >>> p.finalize()
+ b'T\xae\xff3\xbdW\xef\xd5r\x01\xe2n=\xb7\xd2h'
+
+ To check that a given tag is correct use the :meth:`verify` method.
+ You will receive an exception if the tag is wrong:
+
+ .. doctest::
+
+ >>> p = poly1305.Poly1305(key)
+ >>> p.update(b"message to authenticate")
+ >>> p.verify(b"an incorrect tag")
+ Traceback (most recent call last):
+ ...
+ cryptography.exceptions.InvalidSignature: Value did not match computed tag.
+
+ :param key: Secret key as ``bytes``.
+ :type key: :term:`bytes-like`
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the version of OpenSSL ``cryptography`` is compiled against does not
+ support this algorithm.
+
+ .. method:: update(data)
+
+ :param data: The bytes to hash and authenticate.
+ :type data: :term:`bytes-like`
+ :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
+ :raises TypeError: This exception is raised if ``data`` is not ``bytes``.
+
+ .. method:: verify(tag)
+
+ Finalize the current context and securely compare the MAC to
+ ``tag``.
+
+ :param bytes tag: The bytes to compare against.
+ :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
+ :raises cryptography.exceptions.InvalidSignature: If tag does not
+ match.
+ :raises TypeError: This exception is raised if ``tag`` is not
+ ``bytes``.
+
+ .. method:: finalize()
+
+ Finalize the current context and return the message authentication code
+ as bytes.
+
+ After ``finalize`` has been called this object can no longer be used
+ and :meth:`update`, :meth:`verify`, and :meth:`finalize`
+ will raise an :class:`~cryptography.exceptions.AlreadyFinalized`
+ exception.
+
+ :return bytes: The message authentication code as bytes.
+ :raises cryptography.exceptions.AlreadyFinalized:
+
+ .. classmethod:: generate_tag(key, data)
+
+ A single step alternative to do sign operations. Returns the message
+ authentication code as ``bytes`` for the given ``key`` and ``data``.
+
+ :param key: Secret key as ``bytes``.
+ :type key: :term:`bytes-like`
+ :param data: The bytes to hash and authenticate.
+ :type data: :term:`bytes-like`
+ :return bytes: The message authentication code as bytes.
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the version of OpenSSL ``cryptography`` is compiled against does not
+ support this algorithm.
+ :raises TypeError: This exception is raised if ``key`` or ``data`` are
+ not ``bytes``.
+
+ .. doctest::
+
+ >>> poly1305.Poly1305.generate_tag(key, b"message to authenticate")
+ b'T\xae\xff3\xbdW\xef\xd5r\x01\xe2n=\xb7\xd2h'
+
+ .. classmethod:: verify_tag(key, data, tag)
+
+ A single step alternative to do verify operations. Securely compares the
+ MAC to ``tag``, using the given ``key`` and ``data``.
+
+ :param key: Secret key as ``bytes``.
+ :type key: :term:`bytes-like`
+ :param data: The bytes to hash and authenticate.
+ :type data: :term:`bytes-like`
+ :param bytes tag: The bytes to compare against.
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the version of OpenSSL ``cryptography`` is compiled against does not
+ support this algorithm.
+ :raises TypeError: This exception is raised if ``key``, ``data`` or
+ ``tag`` are not ``bytes``.
+ :raises cryptography.exceptions.InvalidSignature: If tag does not match.
+
+ .. doctest::
+
+ >>> poly1305.Poly1305.verify_tag(key, b"message to authenticate", b"an incorrect tag")
+ Traceback (most recent call last):
+ ...
+ cryptography.exceptions.InvalidSignature: Value did not match computed tag.
diff --git a/docs/hazmat/primitives/padding.rst b/docs/hazmat/primitives/padding.rst
index 9581df88b..99d500a05 100644
--- a/docs/hazmat/primitives/padding.rst
+++ b/docs/hazmat/primitives/padding.rst
@@ -107,7 +107,8 @@ multiple of the block size.
.. method:: update(data)
- :param bytes data: The data you wish to pass into the context.
+ :param data: The data you wish to pass into the context.
+ :type data: :term:`bytes-like`
:return bytes: Returns the data that was padded or unpadded.
:raises TypeError: Raised if data is not bytes.
:raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`.
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index 21d12a385..8551acb26 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -11,7 +11,8 @@ where the sender and receiver both use the same secret key. Note that symmetric
encryption is **not** sufficient for most applications because it only
provides secrecy but not authenticity. That means an attacker can't see the
message but an attacker can create bogus messages and force the application to
-decrypt them.
+decrypt them. In many contexts, a lack of authentication on encrypted messages
+can result in a loss of secrecy as well.
For this reason it is **strongly** recommended to combine encryption with a
message authentication code, such as :doc:`HMAC </hazmat/primitives/mac/hmac>`,
@@ -20,7 +21,7 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_.
**To minimize the risk of security issues you should evaluate Fernet to see if
it fits your needs before implementing anything using this module.**
-.. class:: Cipher(algorithm, mode, backend)
+.. class:: Cipher(algorithm, mode, backend=None)
Cipher objects combine an algorithm such as
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES` with a
@@ -33,25 +34,23 @@ it fits your needs before implementing anything using this module.**
>>> import os
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
>>> key = os.urandom(32)
>>> iv = os.urandom(16)
- >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
+ >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
>>> encryptor = cipher.encryptor()
>>> ct = encryptor.update(b"a secret message") + encryptor.finalize()
>>> decryptor = cipher.decryptor()
>>> decryptor.update(ct) + decryptor.finalize()
b'a secret message'
- :param algorithms: A
+ :param algorithm: A
:class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
instance such as those described
:ref:`below <symmetric-encryption-algorithms>`.
:param mode: A :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`
instance such as those described
:ref:`below <symmetric-encryption-modes>`.
- :param backend: A
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
instance.
@@ -147,10 +146,9 @@ Algorithms
.. doctest::
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
- >>> from cryptography.hazmat.backends import default_backend
>>> nonce = os.urandom(16)
>>> algorithm = algorithms.ChaCha20(key, nonce)
- >>> cipher = Cipher(algorithm, mode=None, backend=default_backend())
+ >>> cipher = Cipher(algorithm, mode=None)
>>> encryptor = cipher.encryptor()
>>> ct = encryptor.update(b"a secret message")
>>> decryptor = cipher.decryptor()
@@ -231,9 +229,8 @@ Weak ciphers
.. doctest::
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
- >>> from cryptography.hazmat.backends import default_backend
>>> algorithm = algorithms.ARC4(key)
- >>> cipher = Cipher(algorithm, mode=None, backend=default_backend())
+ >>> cipher = Cipher(algorithm, mode=None)
>>> encryptor = cipher.encryptor()
>>> ct = encryptor.update(b"a secret message")
>>> decryptor = cipher.decryptor()
@@ -418,9 +415,6 @@ Modes
:raises ValueError: This is raised if ``len(tag) < min_tag_length`` or the
``initialization_vector`` is too short.
- :raises NotImplementedError: This is raised if the version of the OpenSSL
- backend used is 1.0.1 or earlier.
-
An example of securely encrypting and decrypting data with ``AES`` in the
``GCM`` mode looks like:
@@ -428,7 +422,6 @@ Modes
import os
- from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import (
Cipher, algorithms, modes
)
@@ -442,7 +435,6 @@ Modes
encryptor = Cipher(
algorithms.AES(key),
modes.GCM(iv),
- backend=default_backend()
).encryptor()
# associated_data will be authenticated but not encrypted,
@@ -461,7 +453,6 @@ Modes
decryptor = Cipher(
algorithms.AES(key),
modes.GCM(iv, tag),
- backend=default_backend()
).decryptor()
# We put associated_data back in or the tag will fail to verify
@@ -598,11 +589,9 @@ Interfaces
>>> import os
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
- >>> from cryptography.hazmat.backends import default_backend
- >>> backend = default_backend()
>>> key = os.urandom(32)
>>> iv = os.urandom(16)
- >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
+ >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
>>> encryptor = cipher.encryptor()
>>> # the buffer needs to be at least len(data) + n - 1 where n is cipher/mode block size in bytes
>>> buf = bytearray(31)
@@ -681,18 +670,12 @@ Interfaces
.. method:: finalize_with_tag(tag)
- .. note::
-
- This method is not supported when compiled against OpenSSL 1.0.1.
-
:param bytes tag: The tag bytes to verify after decryption.
:return bytes: Returns the remainder of the data.
:raises ValueError: This is raised when the data provided isn't
a multiple of the algorithm's block size, if ``min_tag_length`` is
less than 4, or if ``len(tag) < min_tag_length``.
``min_tag_length`` is an argument to the ``GCM`` constructor.
- :raises NotImplementedError: This is raised if the version of the
- OpenSSL backend used is 1.0.1 or earlier.
If the authentication tag was not already supplied to the constructor
of the :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` mode
@@ -828,7 +811,7 @@ Exceptions
.. _`Communications Security Establishment`: https://www.cse-cst.gc.ca
.. _`encrypt`: https://ssd.eff.org/en/module/what-should-i-know-about-encryption
.. _`CRYPTREC`: https://www.cryptrec.go.jp/english/
-.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29
+.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)
.. _`International Data Encryption Algorithm`: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
.. _`OpenPGP`: https://www.openpgp.org/
.. _`disk encryption`: https://en.wikipedia.org/wiki/Disk_encryption_theory#XTS
diff --git a/docs/hazmat/primitives/twofactor.rst b/docs/hazmat/primitives/twofactor.rst
index 51625dfc2..1d2ab452c 100644
--- a/docs/hazmat/primitives/twofactor.rst
+++ b/docs/hazmat/primitives/twofactor.rst
@@ -18,7 +18,7 @@ codes (HMAC).
.. currentmodule:: cryptography.hazmat.primitives.twofactor.hotp
-.. class:: HOTP(key, length, algorithm, backend, enforce_key_length=True)
+.. class:: HOTP(key, length, algorithm, backend=None, enforce_key_length=True)
.. versionadded:: 0.3
@@ -33,11 +33,10 @@ codes (HMAC).
.. doctest::
>>> import os
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.twofactor.hotp import HOTP
>>> from cryptography.hazmat.primitives.hashes import SHA1
>>> key = os.urandom(20)
- >>> hotp = HOTP(key, 6, SHA1(), backend=default_backend())
+ >>> hotp = HOTP(key, 6, SHA1())
>>> hotp_value = hotp.generate(0)
>>> hotp.verify(hotp_value, 0)
@@ -49,15 +48,15 @@ codes (HMAC).
:param cryptography.hazmat.primitives.hashes.HashAlgorithm algorithm: A
:class:`~cryptography.hazmat.primitives.hashes`
instance.
- :param backend: A
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
instance.
:param enforce_key_length: A boolean flag defaulting to True that toggles
whether a minimum key length of 128 :term:`bits` is enforced. This
exists to work around the fact that as documented in `Issue #2915`_,
the Google Authenticator PAM module by default generates 80 bit keys.
- If this flag is set to False, the application develop should implement
- additional checks of the key length before passing it into
+ If this flag is set to False, the application developer should
+ implement additional checks of the key length before passing it into
:class:`~cryptography.hazmat.primitives.twofactor.hotp.HOTP`.
.. versionadded:: 1.5
@@ -129,7 +128,7 @@ similar to the following code.
assert look_ahead >= 0
correct_counter = None
- otp = HOTP(key, 6, default_backend())
+ otp = HOTP(key, 6)
for count in range(counter, counter + look_ahead):
try:
otp.verify(hotp, count)
@@ -141,7 +140,7 @@ similar to the following code.
.. currentmodule:: cryptography.hazmat.primitives.twofactor.totp
-.. class:: TOTP(key, length, algorithm, time_step, backend, enforce_key_length=True)
+.. class:: TOTP(key, length, algorithm, time_step, backend=None, enforce_key_length=True)
TOTP objects take a ``key``, ``length``, ``algorithm`` and ``time_step``
parameter. The ``key`` should be :doc:`randomly generated bytes
@@ -155,11 +154,10 @@ similar to the following code.
>>> import os
>>> import time
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.twofactor.totp import TOTP
>>> from cryptography.hazmat.primitives.hashes import SHA1
>>> key = os.urandom(20)
- >>> totp = TOTP(key, 8, SHA1(), 30, backend=default_backend())
+ >>> totp = TOTP(key, 8, SHA1(), 30)
>>> time_value = time.time()
>>> totp_value = totp.generate(time_value)
>>> totp.verify(totp_value, time_value)
@@ -173,7 +171,7 @@ similar to the following code.
:class:`~cryptography.hazmat.primitives.hashes`
instance.
:param int time_step: The time step size. The recommended size is 30.
- :param backend: A
+ :param backend: An optional
:class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
instance.
:param enforce_key_length: A boolean flag defaulting to True that toggles
diff --git a/docs/index.rst b/docs/index.rst
index 9ff8664e1..ec3913f41 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -19,7 +19,8 @@ key derivation functions. For example, to encrypt something with
'A really secret message. Not for prying eyes.'
If you are interested in learning more about the field of cryptography, we
-recommend `Crypto 101, by Laurens Van Houtven`_.
+recommend `Crypto 101, by Laurens Van Houtven`_ and `The Cryptopals Crypto
+Challenges`_.
Installation
------------
@@ -67,7 +68,6 @@ hazmat layer only when necessary.
exceptions
random-numbers
hazmat/backends/index
- hazmat/bindings/index
.. toctree::
:maxdepth: 2
@@ -92,3 +92,4 @@ hazmat layer only when necessary.
:doc:`get in touch </community>`.
.. _`Crypto 101, by Laurens Van Houtven`: https://www.crypto101.io/
+.. _`The Cryptopals Crypto Challenges`: https://cryptopals.com/
diff --git a/docs/installation.rst b/docs/installation.rst
index 5b2854d96..ea4625582 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -10,29 +10,26 @@ You can install ``cryptography`` with ``pip``:
Supported platforms
-------------------
-Currently we test ``cryptography`` on Python 2.7, 3.4+, and
-PyPy 5.4+ on these operating systems.
+Currently we test ``cryptography`` on Python 2.7, 3.6+,
+PyPy 7.3.1, and PyPy3 7.3.1 on these operating systems.
* x86-64 CentOS 7.x
-* macOS 10.12 Sierra, 10.11 El Capitan
-* x86-64 Ubuntu 14.04, 16.04, and rolling
-* x86-64 Debian Wheezy (7.x), Jessie (8.x), Stretch (9.x), and Sid (unstable)
+* x86-64 & AArch64 CentOS 8.x
+* x86-64 Fedora (latest)
+* x86-64 macOS 10.15 Catalina
+* x86-64 & AArch64 Ubuntu 18.04, 20.04
+* x86-64 Ubuntu rolling
+* x86-64 Debian Stretch (9.x), Buster (10.x), Bullseye (11.x), and Sid
+ (unstable)
* x86-64 Alpine (latest)
-* 32-bit and 64-bit Python on 64-bit Windows Server 2012
+* 32-bit and 64-bit Python on 64-bit Windows Server 2019
We test compiling with ``clang`` as well as ``gcc`` and use the following
OpenSSL releases:
-* ``OpenSSL 1.0.1``
-* ``OpenSSL 1.0.1e-fips`` (``RHEL/CentOS 7``)
-* ``OpenSSL 1.0.1f``
-* ``OpenSSL 1.0.2-latest``
* ``OpenSSL 1.1.0-latest``
* ``OpenSSL 1.1.1-latest``
-.. warning::
- Cryptography 2.4 has deprecated support for OpenSSL 1.0.1.
-
Building cryptography on Windows
--------------------------------
@@ -46,12 +43,11 @@ just run
$ pip install cryptography
If you prefer to compile it yourself you'll need to have OpenSSL installed.
-You can compile OpenSSL yourself as well or use the binaries we build for our
-release infrastructure (`openssl-release`_). Be sure to download the proper
-version for your architecture and Python (2010 works for Python 2.7, 3.3,
-and 3.4 while 2015 is required for 3.5 and above). Wherever you place your copy
-of OpenSSL you'll need to set the ``LIB`` and ``INCLUDE`` environment variables
-to include the proper locations. For example:
+You can compile OpenSSL yourself as well or use `a binary distribution`_.
+Be sure to download the proper version for your architecture and Python
+(VC2010 works for Python 2.7 while VC2015 is required for 3.6 and above).
+Wherever you place your copy of OpenSSL you'll need to set the ``LIB`` and ``INCLUDE``
+environment variables to include the proper locations. For example:
.. code-block:: console
@@ -74,10 +70,10 @@ local `wheel cache`_.
Building cryptography on Linux
------------------------------
-``cryptography`` ships a ``manylinux1`` wheel (as of 2.0) so all dependencies
-are included. For users on pip 8.1 or above running on a ``manylinux1``
-compatible distribution (almost everything except Alpine) all you should
-need to do is:
+``cryptography`` ships ``manylinux`` wheels (as of 2.0) so all dependencies
+are included. For users on pip 8.1 or above running on a ``manylinux1`` or
+``manylinux2010`` compatible distribution (almost everything except Alpine)
+all you should need to do is:
.. code-block:: console
@@ -121,8 +117,8 @@ Building
~~~~~~~~
You should now be able to build and install cryptography. To avoid getting
-the pre-built wheel on ``manylinux1`` distributions you'll need to use
-``--no-binary``.
+the pre-built wheel on ``manylinux`` compatible distributions you'll need to
+use ``--no-binary``.
.. code-block:: console
@@ -162,9 +158,9 @@ Static Wheels
~~~~~~~~~~~~~
Cryptography ships statically-linked wheels for macOS, Windows, and Linux (via
-``manylinux1``). This allows compatible environments to use the most recent
+``manylinux``). This allows compatible environments to use the most recent
OpenSSL, regardless of what is shipped by default on those platforms. Some
-Linux distributions (most notably Alpine) are not ``manylinux1`` compatible so
+Linux distributions (most notably Alpine) are not ``manylinux`` compatible so
we cannot distribute wheels for them.
However, you can build your own statically-linked wheels that will work on your
@@ -228,7 +224,7 @@ users with pip 8 or above you only need one step:
If you want to build cryptography yourself or are on an older macOS version,
cryptography requires the presence of a C compiler, development headers, and
the proper libraries. On macOS much of this is provided by Apple's Xcode
-development tools. To install the Xcode command line tools (on macOS 10.9+)
+development tools. To install the Xcode command line tools (on macOS 10.10+)
open a terminal window and run:
.. code-block:: console
@@ -279,7 +275,7 @@ local `wheel cache`_.
.. _`Homebrew`: https://brew.sh
.. _`MacPorts`: https://www.macports.org
-.. _`openssl-release`: https://ci.cryptography.io/job/cryptography-support-jobs/job/openssl-release-1.1/
+.. _`a binary distribution`: https://wiki.openssl.org/index.php/Binaries
.. _virtualenv: https://virtualenv.pypa.io/en/latest/
.. _openssl.org: https://www.openssl.org/source/
.. _`wheel cache`: https://pip.pypa.io/en/stable/reference/pip_install/#caching
diff --git a/docs/limitations.rst b/docs/limitations.rst
index 503bdfe48..5763ecd40 100644
--- a/docs/limitations.rst
+++ b/docs/limitations.rst
@@ -1,19 +1,44 @@
Known security limitations
---------------------------
+==========================
-Lack of secure memory wiping
-============================
+Secure memory wiping
+--------------------
`Memory wiping`_ is used to protect secret data or key material from attackers
-with access to uninitialized memory. This can be either because the attacker
-has some kind of local user access or because of how other software uses
-uninitialized memory.
+with access to deallocated memory. This is a defense-in-depth measure against
+vulnerabilities that leak application memory.
-Python exposes no API for us to implement this reliably and as such almost all
-software in Python is potentially vulnerable to this attack. The
+Many ``cryptography`` APIs which accept ``bytes`` also accept types which
+implement the buffer interface. Thus, users wishing to do so can pass
+``memoryview`` or another mutable type to ``cryptography`` APIs, and overwrite
+the contents once the data is no longer needed.
+
+However, ``cryptography`` does not clear memory by default, as there is no way
+to clear immutable structures such as ``bytes``. As a result, ``cryptography``,
+like almost all software in Python is potentially vulnerable to this attack. The
`CERT secure coding guidelines`_ assesses this issue as "Severity: medium,
Likelihood: unlikely, Remediation Cost: expensive to repair" and we do not
consider this a high risk for most users.
-.. _`Memory wiping`: https://blogs.msdn.microsoft.com/oldnewthing/20130529-00/?p=4223/
-.. _`CERT secure coding guidelines`: https://www.securecoding.cert.org/confluence/display/c/MEM03-C.+Clear+sensitive+information+stored+in+reusable+resources
+RSA PKCS1 v1.5 constant time decryption
+---------------------------------------
+
+RSA decryption has several different modes, one of which is PKCS1 v1.5. When
+used in online contexts, a secure protocol implementation requires that peers
+not be able to tell whether RSA PKCS1 v1.5 decryption failed or succeeded,
+even by timing variability.
+
+``cryptography`` does not provide an API that makes this possible, due to the
+fact that RSA decryption raises an exception on failure, which takes a
+different amount of time than returning a value in the success case.
+
+For this reason, at present, we recommend not implementing online protocols
+that use RSA PKCS1 v1.5 decryption with ``cryptography`` -- independent of this
+limitation, such protocols generally have poor security properties due to their
+lack of forward security.
+
+If a constant time RSA PKCS1 v1.5 decryption API is truly required, you should
+contribute one to ``cryptography``.
+
+.. _`Memory wiping`: https://devblogs.microsoft.com/oldnewthing/?p=4223
+.. _`CERT secure coding guidelines`: https://wiki.sei.cmu.edu/confluence/display/c/MEM03-C.+Clear+sensitive+information+stored+in+reusable+resources
diff --git a/docs/security.rst b/docs/security.rst
index 01845a48c..d11f27000 100644
--- a/docs/security.rst
+++ b/docs/security.rst
@@ -9,9 +9,9 @@ Infrastructure
--------------
In addition to ``cryptography``'s code, we're also concerned with the security
-of the infrastructure we run (primarily ``cryptography.io`` and
-``ci.cryptography.io``). If you discover a security vulnerability in our
-infrastructure, we ask you to report it using the same procedure.
+of the infrastructure we run (primarily ``cryptography.io``). If you discover
+a security vulnerability in our infrastructure, we ask you to report it using
+the same procedure.
What is a security issue?
-------------------------
@@ -53,10 +53,9 @@ We ask that you do not report security issues to our normal GitHub issue
tracker.
If you believe you've identified a security issue with ``cryptography``, please
-report it to ``alex.gaynor@gmail.com``. Messages may be optionally encrypted
-with PGP using key fingerprint
-``F7FC 698F AAE2 D2EF BECD E98E D1B3 ADC0 E023 8CA6`` (this public key is
-available from most commonly-used key servers).
+report it to ``alex.gaynor@gmail.com`` and/or ``paul.l.kehrer@gmail.com``. You
+should verify that your MTA uses TLS to ensure the confidentiality of your
+message.
Once you've submitted an issue via email, you should receive an acknowledgment
within 48 hours, and depending on the action to be taken, you may receive
@@ -72,9 +71,9 @@ New releases for OpenSSL updates
--------------------------------
As of versions 0.5, 1.0.1, and 2.0.0, ``cryptography`` statically links OpenSSL
-on Windows, macOS, and Linux respectively, to ease installation. Due to this,
-``cryptography`` will release a new version whenever OpenSSL has a security or
-bug fix release to avoid shipping insecure software.
+in binary distributions for Windows, macOS, and Linux respectively, to ease
+installation. Due to this, ``cryptography`` will release a new version whenever
+OpenSSL has a security or bug fix release to avoid shipping insecure software.
Like all our other releases, this will be announced on the mailing list and we
strongly recommend that you upgrade as soon as possible.
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index 7e08f1241..f0486e05f 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -1,14 +1,18 @@
+AArch
accessor
affine
Authenticator
+authenticator
backend
Backends
backends
bcrypt
+Bleichenbacher
Blowfish
boolean
Botan
Brainpool
+Bullseye
Capitan
changelog
Changelog
@@ -17,11 +21,13 @@ codebook
committer
committers
conda
+CPython
Cryptanalysis
crypto
cryptographic
cryptographically
Debian
+deallocated
decrypt
decrypts
Decrypts
@@ -50,9 +56,9 @@ Google
hazmat
Homebrew
hostname
-idna
indistinguishability
initialisms
+interoperability
interoperable
introspectability
invariants
@@ -76,6 +82,7 @@ Parallelization
personalization
pickleable
plaintext
+Poly
pre
precompute
preprocessor
@@ -83,6 +90,7 @@ preprocessors
presentational
pseudorandom
pyOpenSSL
+pytest
relicensed
responder
runtime
@@ -95,6 +103,7 @@ Solaris
syscall
Tanja
testability
+Thawte
timestamp
timestamps
tunable
diff --git a/docs/x509/ocsp.rst b/docs/x509/ocsp.rst
index d3815d6f3..0c2d07aef 100644
--- a/docs/x509/ocsp.rst
+++ b/docs/x509/ocsp.rst
@@ -167,12 +167,11 @@ Creating Requests
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import serialization
>>> from cryptography.hazmat.primitives.hashes import SHA1
>>> from cryptography.x509 import load_pem_x509_certificate, ocsp
- >>> cert = load_pem_x509_certificate(pem_cert, default_backend())
- >>> issuer = load_pem_x509_certificate(pem_issuer, default_backend())
+ >>> cert = load_pem_x509_certificate(pem_cert)
+ >>> issuer = load_pem_x509_certificate(pem_issuer)
>>> builder = ocsp.OCSPRequestBuilder()
>>> # SHA1 is in this example because RFC 5019 mandates its use.
>>> builder = builder.add_certificate(cert, issuer, SHA1())
@@ -292,27 +291,35 @@ Creating Responses
:attr:`~cryptography.x509.ocsp.OCSPResponseStatus.SUCCESSFUL` response.
:param private_key: The
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`
- or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
that will be used to sign the certificate.
:param algorithm: The
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
- will be used to generate the signature.
+ will be used to generate the signature. This must be ``None`` if
+ the ``private_key`` is an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+ or an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ and an instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ otherwise.
:returns: A new :class:`~cryptography.x509.ocsp.OCSPResponse`.
.. doctest::
>>> import datetime
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes, serialization
>>> from cryptography.x509 import load_pem_x509_certificate, ocsp
- >>> cert = load_pem_x509_certificate(pem_cert, default_backend())
- >>> issuer = load_pem_x509_certificate(pem_issuer, default_backend())
- >>> responder_cert = load_pem_x509_certificate(pem_responder_cert, default_backend())
- >>> responder_key = serialization.load_pem_private_key(pem_responder_key, None, default_backend())
+ >>> cert = load_pem_x509_certificate(pem_cert)
+ >>> issuer = load_pem_x509_certificate(pem_issuer)
+ >>> responder_cert = load_pem_x509_certificate(pem_responder_cert)
+ >>> responder_key = serialization.load_pem_private_key(pem_responder_key, None)
>>> builder = ocsp.OCSPResponseBuilder()
>>> # SHA1 is in this example because RFC 5019 mandates its use.
>>> builder = builder.add_response(
@@ -341,7 +348,6 @@ Creating Responses
.. doctest::
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes, serialization
>>> from cryptography.x509 import load_pem_x509_certificate, ocsp
>>> response = ocsp.OCSPResponseBuilder.build_unsuccessful(
@@ -434,7 +440,10 @@ Interfaces
Returns the
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
- was used in signing this response.
+ was used in signing this response. Can be ``None`` if signature
+ did not use separate hash
+ (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+ :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
.. attribute:: signature
@@ -589,6 +598,14 @@ Interfaces
The extensions encoded in the response.
+ .. attribute:: single_extensions
+
+ .. versionadded:: 2.9
+
+ :type: :class:`~cryptography.x509.Extensions`
+
+ The single extensions encoded in the response.
+
.. method:: public_bytes(encoding)
:param encoding: The encoding to use. Only
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index b2278d57f..a46c5d623 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -22,22 +22,20 @@ X.509 Reference
pem_req_data = b"""
-----BEGIN CERTIFICATE REQUEST-----
- MIIC0zCCAbsCAQAwWTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCElsbGlub2lzMRAw
- DgYDVQQHDAdDaGljYWdvMREwDwYDVQQKDAhyNTA5IExMQzESMBAGA1UEAwwJaGVs
- bG8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqhZx+Mo9VRd9
- vsnWWa6NBCws21rZ0+1B/JGgB4hDsZS7iDE4Bj5z4idheFRtl8bBbdjPknq7BfoF
- 8v15Zq/Zv7i2xMSDL+LUrTBZezRd4bRTGqCm6YJ5EYkhqdcqeZleHCFImguHoq1J
- Fh0+kObQrTHXw3ZP57a3o1IvyIUA3nNoCBL0QQhwBXaDXOojMKNR+bqB5ve8GS1y
- Elr0AM/+cJsfaIahNQUgFKx3Eu3GeEOMKYOAG1lycgdQdmTUybLrT3U7vkClTseM
- xHg1r5En7ALjONIhqRuq3rddYahrP8HXozb3zUy3cJ7P6IeaosuvNzvMXOX9P6HD
- Ha9urDAJ1wIDAQABoDUwMwYJKoZIhvcNAQkOMSYwJDAiBgNVHREEGzAZggl3b3Js
- ZC5jb22CDHdoYXRldmVyLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAS4Ro6h+z52SK
- YSLCYARpnEu/rmh4jdqndt8naqcNb6uLx9mlKZ2W9on9XDjnSdQD9q+ZP5aZfESw
- R0+rJhW9ZrNa/g1pt6M24ihclHYDAxYMWxT1z/TXXGM3TmZZ6gfYlNE1kkBuODHa
- UYsR/1Ht1E1EsmmUimt2n+zQR2K8T9Coa+boaUW/GsTEuz1aaJAkj5ZvTDiIhRG4
- AOCqFZOLAQmCCNgJnnspD9hDz/Ons085LF5wnYjN4/Nsk5tS6AGs3xjZ3jPoOGGn
- 82WQ9m4dBGoVDZXsobVTaN592JEYwN5iu72zRn7Einb4V4H5y3yD2dD4yWPlt4pk
- 5wFkeYsZEA==
+ MIICcDCCAVgCAQAwDTELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+ DwAwggEKAoIBAQCb+ec0zYAYLzk/MDdDJYvzdvEO2ZUrBYM6z1r8NedwpJfxUWqC
+ hvK1cpc9EbQeCwS1eooTIGoNveeCrwL+pWdmf1sh6gz7SsxdN/07nyhSM8M6Xkec
+ +tGrjyi1H/N1afwWXox3WcvBNbxu3Df5RKLDb0yt9aqhmJylbl/tbvgJesXymwmp
+ Rc1vXL0fOedUtuAJ3xQ15M0pgLF8qDn4lySJz25x76pMYPeN5/a7x+SR/jj81kep
+ VaVpuh/2hePV5uwUX3uWoj5sAkrBCifi4NPge0Npd6KeKVvXytLOymH/4+WvV719
+ wCO+MyrkhpdHSakJDTIaQIxsqVeVVKdPLAPJAgMBAAGgHjAcBgkqhkiG9w0BCQcx
+ DwwNY2hhbGxlbmdlIG1lITANBgkqhkiG9w0BAQsFAAOCAQEAMmgeSa8szbjPFD/4
+ vcPBr/vBEROFGgL8mX3o5pF9gpr7nRjhLKBkgJvlRm6Ma3Xvdfc/r5Hp2ZBTA7sZ
+ ZYhyeezGfCQN/Qhda1v+sCwG58IjvGfCSS7Y5tGlEBQ4MDf0Q7PYPSxaNUEBH7vo
+ +M7U+nFuNSmyWlt6SFBSkohZkWoVSGx3KsAO+SAHYZ7JtqsAS/dm7Dflp8KxeDg7
+ wzGBDQRpGF4CpI1VQjGSJQXSEdD+J7mtvBEOD34abRfV6zOUGzOOo3NWE6wNpYgt
+ 0A7gVlzSYpdwqjBdvACfXR2r/mu+4KkAvYh8WwCiTcYgGjl2pT1bO4hEmcJ0RSWy
+ /fGD8Q==
-----END CERTIFICATE REQUEST-----
""".strip()
@@ -151,7 +149,7 @@ X.509 Reference
Loading Certificates
~~~~~~~~~~~~~~~~~~~~
-.. function:: load_pem_x509_certificate(data, backend)
+.. function:: load_pem_x509_certificate(data, backend=None)
.. versionadded:: 0.7
@@ -161,7 +159,7 @@ Loading Certificates
:param bytes data: The PEM encoded certificate data.
- :param backend: A backend supporting the
+ :param backend: An optional backend supporting the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -170,12 +168,11 @@ Loading Certificates
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
- >>> cert = x509.load_pem_x509_certificate(pem_data, default_backend())
+ >>> cert = x509.load_pem_x509_certificate(pem_data)
>>> cert.serial_number
2
-.. function:: load_der_x509_certificate(data, backend)
+.. function:: load_der_x509_certificate(data, backend=None)
.. versionadded:: 0.7
@@ -185,7 +182,7 @@ Loading Certificates
:param bytes data: The DER encoded certificate data.
- :param backend: A backend supporting the
+ :param backend: An optional backend supporting the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -194,7 +191,7 @@ Loading Certificates
Loading Certificate Revocation Lists
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. function:: load_pem_x509_crl(data, backend)
+.. function:: load_pem_x509_crl(data, backend=None)
.. versionadded:: 1.1
@@ -204,7 +201,7 @@ Loading Certificate Revocation Lists
:param bytes data: The PEM encoded request data.
- :param backend: A backend supporting the
+ :param backend: An optional backend supporting the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -214,13 +211,12 @@ Loading Certificate Revocation Lists
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
- >>> crl = x509.load_pem_x509_crl(pem_crl_data, default_backend())
+ >>> crl = x509.load_pem_x509_crl(pem_crl_data)
>>> isinstance(crl.signature_hash_algorithm, hashes.SHA256)
True
-.. function:: load_der_x509_crl(data, backend)
+.. function:: load_der_x509_crl(data, backend=None)
.. versionadded:: 1.1
@@ -229,7 +225,7 @@ Loading Certificate Revocation Lists
:param bytes data: The DER encoded request data.
- :param backend: A backend supporting the
+ :param backend: An optional backend supporting the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -239,7 +235,7 @@ Loading Certificate Revocation Lists
Loading Certificate Signing Requests
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. function:: load_pem_x509_csr(data, backend)
+.. function:: load_pem_x509_csr(data, backend=None)
.. versionadded:: 0.9
@@ -250,7 +246,7 @@ Loading Certificate Signing Requests
:param bytes data: The PEM encoded request data.
- :param backend: A backend supporting the
+ :param backend: An optional backend supporting the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -260,13 +256,12 @@ Loading Certificate Signing Requests
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
- >>> csr = x509.load_pem_x509_csr(pem_req_data, default_backend())
- >>> isinstance(csr.signature_hash_algorithm, hashes.SHA1)
+ >>> csr = x509.load_pem_x509_csr(pem_req_data)
+ >>> isinstance(csr.signature_hash_algorithm, hashes.SHA256)
True
-.. function:: load_der_x509_csr(data, backend)
+.. function:: load_der_x509_csr(data, backend=None)
.. versionadded:: 0.9
@@ -275,7 +270,7 @@ Loading Certificate Signing Requests
:param bytes data: The DER encoded request data.
- :param backend: A backend supporting the
+ :param backend: An optional backend supporting the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -335,10 +330,12 @@ X.509 Certificate Object
The public key associated with the certificate.
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`
.. doctest::
@@ -393,7 +390,10 @@ X.509 Certificate Object
Returns the
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
- was used in signing this certificate.
+ was used in signing this certificate. Can be ``None`` if signature
+ did not use separate hash
+ (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+ :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
.. doctest::
@@ -429,16 +429,13 @@ X.509 Certificate Object
:raises cryptography.x509.UnsupportedGeneralNameType: If an extension
contains a general name that is not supported.
- :raises UnicodeError: If an extension contains IDNA encoding that is
- invalid or not compliant with IDNA 2008.
-
.. doctest::
>>> for ext in cert.extensions:
... print(ext)
<Extension(oid=<ObjectIdentifier(oid=2.5.29.35, name=authorityKeyIdentifier)>, critical=False, value=<AuthorityKeyIdentifier(key_identifier=b'\xe4}_\xd1\\\x95\x86\x08,\x05\xae\xbeu\xb6e\xa7\xd9]\xa8f', authority_cert_issuer=None, authority_cert_serial_number=None)>)>
<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectKeyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(digest=b'X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9')>)>
- <Extension(oid=<ObjectIdentifier(oid=2.5.29.15, name=keyUsage)>, critical=True, value=<KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=None, decipher_only=None)>)>
+ <Extension(oid=<ObjectIdentifier(oid=2.5.29.15, name=keyUsage)>, critical=True, value=<KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=False, decipher_only=False)>)>
<Extension(oid=<ObjectIdentifier(oid=2.5.29.32, name=certificatePolicies)>, critical=False, value=<CertificatePolicies([<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=2.16.840.1.101.3.2.1.48.1, name=Unknown OID)>, policy_qualifiers=None)>])>)>
<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
@@ -474,8 +471,8 @@ X.509 Certificate Object
>>> from cryptography.hazmat.primitives.serialization import load_pem_public_key
>>> from cryptography.hazmat.primitives.asymmetric import padding
- >>> issuer_public_key = load_pem_public_key(pem_issuer_public_key, default_backend())
- >>> cert_to_check = x509.load_pem_x509_certificate(pem_data_to_check, default_backend())
+ >>> issuer_public_key = load_pem_public_key(pem_issuer_public_key)
+ >>> cert_to_check = x509.load_pem_x509_certificate(pem_data_to_check)
>>> issuer_public_key.verify(
... cert_to_check.signature,
... cert_to_check.tbs_certificate_bytes,
@@ -551,7 +548,10 @@ X.509 CRL (Certificate Revocation List) Object
Returns the
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
- was used in signing this CRL.
+ was used in signing this CRL. Can be ``None`` if signature
+ did not use separate hash
+ (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+ :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
.. doctest::
@@ -601,7 +601,7 @@ X.509 CRL (Certificate Revocation List) Object
:type: :class:`datetime.datetime`
- A naïve datetime representing when the this CRL was last updated.
+ A naïve datetime representing when this CRL was last updated.
.. doctest::
@@ -668,7 +668,6 @@ X.509 Certificate Builder
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> from cryptography.x509.oid import NameOID
@@ -677,7 +676,6 @@ X.509 Certificate Builder
>>> private_key = rsa.generate_private_key(
... public_exponent=65537,
... key_size=2048,
- ... backend=default_backend()
... )
>>> public_key = private_key.public_key()
>>> builder = x509.CertificateBuilder()
@@ -702,7 +700,6 @@ X.509 Certificate Builder
... )
>>> certificate = builder.sign(
... private_key=private_key, algorithm=hashes.SHA256(),
- ... backend=default_backend()
... )
>>> isinstance(certificate, x509.Certificate)
True
@@ -727,8 +724,10 @@ X.509 Certificate Builder
:param public_key: The subject's public key. This can be one of
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
.. method:: serial_number(serial_number)
@@ -775,21 +774,30 @@ X.509 Certificate Builder
:param critical: Set to ``True`` if the extension must be understood and
handled by whoever reads the certificate.
- .. method:: sign(private_key, algorithm, backend)
+ .. method:: sign(private_key, algorithm, backend=None)
Sign the certificate using the CA's private key.
:param private_key: The
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
that will be used to sign the certificate.
:param algorithm: The
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
- will be used to generate the signature.
+ will be used to generate the signature. This must be ``None`` if
+ the ``private_key`` is an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+ or an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ and an instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ otherwise.
- :param backend: Backend that will be used to build the certificate.
+ :param backend: An optional backend used to build the certificate.
Must support the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -808,10 +816,12 @@ X.509 CSR (Certificate Signing Request) Object
The public key associated with the request.
- :returns:
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`
+ :returns: One of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
.. doctest::
@@ -832,12 +842,15 @@ X.509 CSR (Certificate Signing Request) Object
Returns the
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` which
- was used in signing this request.
+ was used in signing this request. Can be ``None`` if signature
+ did not use separate hash
+ (:attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED25519`,
+ :attr:`~cryptography.x509.oid.SignatureAlgorithmOID.ED448`).
.. doctest::
>>> from cryptography.hazmat.primitives import hashes
- >>> isinstance(csr.signature_hash_algorithm, hashes.SHA1)
+ >>> isinstance(csr.signature_hash_algorithm, hashes.SHA256)
True
.. attribute:: signature_algorithm_oid
@@ -853,7 +866,7 @@ X.509 CSR (Certificate Signing Request) Object
.. doctest::
>>> csr.signature_algorithm_oid
- <ObjectIdentifier(oid=1.2.840.113549.1.1.5, name=sha1WithRSAEncryption)>
+ <ObjectIdentifier(oid=1.2.840.113549.1.1.11, name=sha256WithRSAEncryption)>
.. attribute:: extensions
@@ -867,9 +880,17 @@ X.509 CSR (Certificate Signing Request) Object
:raises cryptography.x509.UnsupportedGeneralNameType: If an extension
contains a general name that is not supported.
- :raises UnicodeError: If an extension contains IDNA encoding that is
- invalid or not compliant with IDNA 2008.
+ .. method:: get_attribute_for_oid(oid)
+ .. versionadded:: 3.0
+
+ :param oid: An :class:`ObjectIdentifier` instance.
+
+ :returns: The bytes value of the attribute or an exception if not
+ found.
+
+ :raises cryptography.x509.AttributeNotFound: If the request does
+ not have the attribute requested.
.. method:: public_bytes(encoding)
@@ -918,7 +939,6 @@ X.509 Certificate Revocation List Builder
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> from cryptography.x509.oid import NameOID
@@ -927,7 +947,6 @@ X.509 Certificate Revocation List Builder
>>> private_key = rsa.generate_private_key(
... public_exponent=65537,
... key_size=2048,
- ... backend=default_backend()
... )
>>> builder = x509.CertificateRevocationListBuilder()
>>> builder = builder.issuer_name(x509.Name([
@@ -939,11 +958,10 @@ X.509 Certificate Revocation List Builder
... 333
... ).revocation_date(
... datetime.datetime.today()
- ... ).build(default_backend())
+ ... ).build()
>>> builder = builder.add_revoked_certificate(revoked_cert)
>>> crl = builder.sign(
... private_key=private_key, algorithm=hashes.SHA256(),
- ... backend=default_backend()
... )
>>> len(crl)
1
@@ -994,21 +1012,30 @@ X.509 Certificate Revocation List Builder
obtained from an existing CRL or created with
:class:`~cryptography.x509.RevokedCertificateBuilder`.
- .. method:: sign(private_key, algorithm, backend)
+ .. method:: sign(private_key, algorithm, backend=None)
Sign this CRL using the CA's private key.
:param private_key: The
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
that will be used to sign the certificate.
:param algorithm: The
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` that
will be used to generate the signature.
+ This must be ``None`` if the ``private_key`` is an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+ or an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ and an instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ otherwise.
- :param backend: Backend that will be used to build the CRL.
+ :param backend: An optional backend used to build the CRL.
Must support the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -1071,12 +1098,11 @@ X.509 Revoked Certificate Builder
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
>>> import datetime
>>> builder = x509.RevokedCertificateBuilder()
>>> builder = builder.revocation_date(datetime.datetime.today())
>>> builder = builder.serial_number(3333)
- >>> revoked_certificate = builder.build(default_backend())
+ >>> revoked_certificate = builder.build()
>>> isinstance(revoked_certificate, x509.RevokedCertificate)
True
@@ -1104,11 +1130,11 @@ X.509 Revoked Certificate Builder
:param critical: Set to ``True`` if the extension must be understood and
handled.
- .. method:: build(backend)
+ .. method:: build(backend=None)
Create a revoked certificate object using the provided backend.
- :param backend: Backend that will be used to build the revoked
+ :param backend: An optional backend used to build the revoked
certificate. Must support the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -1125,14 +1151,12 @@ X.509 CSR (Certificate Signing Request) Builder Object
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import rsa
- >>> from cryptography.x509.oid import NameOID
+ >>> from cryptography.x509.oid import AttributeOID, NameOID
>>> private_key = rsa.generate_private_key(
... public_exponent=65537,
... key_size=2048,
- ... backend=default_backend()
... )
>>> builder = x509.CertificateSigningRequestBuilder()
>>> builder = builder.subject_name(x509.Name([
@@ -1141,8 +1165,11 @@ X.509 CSR (Certificate Signing Request) Builder Object
>>> builder = builder.add_extension(
... x509.BasicConstraints(ca=False, path_length=None), critical=True,
... )
+ >>> builder = builder.add_attribute(
+ ... AttributeOID.CHALLENGE_PASSWORD, b"changeit"
+ ... )
>>> request = builder.sign(
- ... private_key, hashes.SHA256(), default_backend()
+ ... private_key, hashes.SHA256()
... )
>>> isinstance(request, x509.CertificateSigningRequest)
True
@@ -1163,17 +1190,29 @@ X.509 CSR (Certificate Signing Request) Builder Object
:returns: A new
:class:`~cryptography.x509.CertificateSigningRequestBuilder`.
- .. method:: sign(private_key, algorithm, backend)
+ .. method:: add_attribute(oid, value)
- :param backend: Backend that will be used to sign the request.
+ .. versionadded:: 3.0
+
+ :param oid: An :class:`ObjectIdentifier` instance.
+ :param value: The value of the attribute.
+ :type value: bytes
+ :returns: A new
+ :class:`~cryptography.x509.CertificateSigningRequestBuilder`.
+
+ .. method:: sign(private_key, algorithm, backend=None)
+
+ :param backend: An optional backend used to sign the request.
Must support the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
:param private_key: The
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`,
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey` or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
that will be used to sign the request. When the request is
signed by a certificate authority, the private key's associated
public key will be stored in the resulting certificate.
@@ -1181,6 +1220,13 @@ X.509 CSR (Certificate Signing Request) Builder Object
:param algorithm: The
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
that will be used to generate the request signature.
+ This must be ``None`` if the ``private_key`` is an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`
+ or an
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey`
+ and an instance of a
+ :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
+ otherwise.
:returns: A new
:class:`~cryptography.x509.CertificateSigningRequest`.
@@ -1236,11 +1282,11 @@ X.509 CSR (Certificate Signing Request) Builder Object
>>> cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)
[<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='Good CA')>]
- .. method:: public_bytes(backend)
+ .. method:: public_bytes(backend=None)
.. versionadded:: 1.6
- :param backend: A backend supporting the
+ :param backend: An optional backend supporting the
:class:`~cryptography.hazmat.backends.interfaces.X509Backend`
interface.
@@ -1348,17 +1394,10 @@ General Name Classes
.. versionadded:: 0.9
- .. versionchanged:: 2.1
-
- .. warning::
-
- Starting with version 2.1 :term:`U-label` input is deprecated. If
- passing an internationalized domain name (IDN) you should first IDNA
- encode the value and then pass the result as a string. Accessing
- ``value`` will return the :term:`A-label` encoded form even if you pass
- a U-label. This breaks backwards compatibility, but only for
- internationalized domain names.
+ .. versionchanged:: 3.1
+ :term:`U-label` support has been removed. Encode them to
+ :term:`A-label` before use.
This corresponds to an email address. For example, ``user@example.com``.
@@ -1366,6 +1405,8 @@ General Name Classes
internationalized domain name then it must be encoded to an
:term:`A-label` string before being passed.
+ :raises ValueError: If the provided string is not an :term:`A-label`.
+
.. attribute:: value
:type: :term:`text`
@@ -1374,16 +1415,10 @@ General Name Classes
.. versionadded:: 0.9
- .. versionchanged:: 2.1
+ .. versionchanged:: 3.1
- .. warning::
-
- Starting with version 2.1 :term:`U-label` input is deprecated. If
- passing an internationalized domain name (IDN) you should first IDNA
- encode the value and then pass the result as a string. Accessing
- ``value`` will return the :term:`A-label` encoded form even if you pass
- a U-label. This breaks backwards compatibility, but only for
- internationalized domain names.
+ :term:`U-label` support has been removed. Encode them to
+ :term:`A-label` before use.
This corresponds to a domain name. For example, ``cryptography.io``.
@@ -1391,6 +1426,8 @@ General Name Classes
name then it must be encoded to an :term:`A-label` string before being
passed.
+ :raises ValueError: If the provided string is not an :term:`A-label`.
+
:type: :term:`text`
.. attribute:: value
@@ -1411,16 +1448,10 @@ General Name Classes
.. versionadded:: 0.9
- .. versionchanged:: 2.1
-
- .. warning::
+ .. versionchanged:: 3.1
- Starting with version 2.1 :term:`U-label` input is deprecated. If
- passing an internationalized domain name (IDN) you should first IDNA
- encode the value and then pass the result as a string. Accessing
- ``value`` will return the :term:`A-label` encoded form even if you pass
- a U-label. This breaks backwards compatibility, but only for
- internationalized domain names.
+ :term:`U-label` support has been removed. Encode them to
+ :term:`A-label` before use.
This corresponds to a uniform resource identifier. For example,
``https://cryptography.io``.
@@ -1429,6 +1460,8 @@ General Name Classes
name then it must be encoded to an :term:`A-label` string before
being passed.
+ :raises ValueError: If the provided string is not an :term:`A-label`.
+
.. attribute:: value
:type: :term:`text`
@@ -1821,7 +1854,7 @@ X.509 Extensions
:type: A list of :class:`GeneralName` instances or None
- The :class:`Name` of the issuer's issuer.
+ The :class:`GeneralName` (one or multiple) of the issuer's issuer.
.. attribute:: authority_cert_serial_number
@@ -1853,17 +1886,16 @@ X.509 Extensions
section 4.2.1.2.
:param public_key: One of
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
- ,
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
- , or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`.
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
- >>> issuer_cert = x509.load_pem_x509_certificate(pem_data, default_backend())
+ >>> issuer_cert = x509.load_pem_x509_certificate(pem_data)
>>> x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_cert.public_key())
<AuthorityKeyIdentifier(key_identifier=b'X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9', authority_cert_issuer=None, authority_cert_serial_number=None)>
@@ -1892,10 +1924,9 @@ X.509 Extensions
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
- >>> issuer_cert = x509.load_pem_x509_certificate(pem_data, default_backend())
- >>> ski = issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
- >>> x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ski)
+ >>> issuer_cert = x509.load_pem_x509_certificate(pem_data)
+ >>> ski_ext = issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
+ >>> x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ski_ext.value)
<AuthorityKeyIdentifier(key_identifier=b'X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9', authority_cert_issuer=None, authority_cert_serial_number=None)>
.. class:: SubjectKeyIdentifier(digest)
@@ -1931,19 +1962,18 @@ X.509 Extensions
recommendation in :rfc:`5280` section 4.2.1.2.
:param public_key: One of
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
- ,
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
- , or
- :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`.
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey`,
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey` or
+ :class:`~cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey`.
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
- >>> csr = x509.load_pem_x509_csr(pem_req_data, default_backend())
+ >>> csr = x509.load_pem_x509_csr(pem_req_data)
>>> x509.SubjectKeyIdentifier.from_public_key(csr.public_key())
- <SubjectKeyIdentifier(digest=b'\xdb\xaa\xf0\x06\x11\xdbD\xfe\xbf\x93\x03\x8av\x88WP7\xa6\x91\xf7')>
+ <SubjectKeyIdentifier(digest=b'\x8c"\x98\xe2\xb5\xbf]\xe8*2\xf8\xd2\'?\x00\xd2\xc7#\xe4c')>
.. class:: SubjectAlternativeName(general_names)
@@ -1976,9 +2006,8 @@ X.509 Extensions
.. doctest::
>>> from cryptography import x509
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
- >>> cert = x509.load_pem_x509_certificate(cryptography_cert_pem, default_backend())
+ >>> cert = x509.load_pem_x509_certificate(cryptography_cert_pem)
>>> # Get the subjectAltName extension from the certificate
>>> ext = cert.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
>>> # Get the dNSName entries from the SAN extension
@@ -2057,6 +2086,33 @@ X.509 Extensions
Returns :attr:`~cryptography.x509.oid.ExtensionOID.PRECERT_POISON`.
+.. class:: SignedCertificateTimestamps(scts)
+
+ .. versionadded:: 3.0
+
+ This extension contains
+ :class:`~cryptography.x509.certificate_transparency.SignedCertificateTimestamp`
+ instances. These can be used to verify that the certificate is included
+ in a public Certificate Transparency log. This extension is only found
+ in OCSP responses. For SCTs in an X.509 certificate see
+ :class:`~cryptography.x509.PrecertificateSignedCertificateTimestamps`.
+
+ It is an iterable containing one or more
+ :class:`~cryptography.x509.certificate_transparency.SignedCertificateTimestamp`
+ objects.
+
+ :param list scts: A ``list`` of
+ :class:`~cryptography.x509.certificate_transparency.SignedCertificateTimestamp`
+ objects.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS`.
+
+
.. class:: DeltaCRLIndicator(crl_number)
.. versionadded:: 2.1
@@ -2104,6 +2160,29 @@ X.509 Extensions
:attr:`~cryptography.x509.oid.ExtensionOID.AUTHORITY_INFORMATION_ACCESS`.
+.. class:: SubjectInformationAccess(descriptions)
+
+ .. versionadded:: 3.0
+
+ The subject information access extension indicates how to access
+ information and services for the subject of the certificate in which
+ the extension appears. When the subject is a CA, information and
+ services may include certificate validation services and CA policy
+ data. When the subject is an end entity, the information describes
+ the type of services offered and how to access them. It is an iterable,
+ containing one or more :class:`~cryptography.x509.AccessDescription`
+ instances.
+
+ :param list descriptions: A list of :class:`AccessDescription` objects.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.SUBJECT_INFORMATION_ACCESS`.
+
+
.. class:: AccessDescription(access_method, access_location)
.. versionadded:: 0.9
@@ -2113,16 +2192,23 @@ X.509 Extensions
:type: :class:`ObjectIdentifier`
The access method defines what the ``access_location`` means. It must
- be either
+ be
:attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.OCSP` or
- :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.CA_ISSUERS`.
+ :attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.CA_ISSUERS`
+ when used with :class:`~cryptography.x509.AuthorityInformationAccess`
+ or
+ :attr:`~cryptography.x509.oid.SubjectInformationAccessOID.CA_REPOSITORY`
+ when used with :class:`~cryptography.x509.SubjectInformationAccess`.
+
If it is
:attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.OCSP`
the access location will be where to obtain OCSP
information for the certificate. If it is
:attr:`~cryptography.x509.oid.AuthorityInformationAccessOID.CA_ISSUERS`
the access location will provide additional information about the
- issuing certificate.
+ issuing certificate. Finally, if it is
+ :attr:`~cryptography.x509.oid.SubjectInformationAccessOID.CA_REPOSITORY`
+ the access location will be the location of the CA's repository.
.. attribute:: access_location
@@ -2418,7 +2504,9 @@ X.509 Extensions
.. versionadded:: 1.2
A generic extension class used to hold the raw value of extensions that
- ``cryptography`` does not know how to parse.
+ ``cryptography`` does not know how to parse. This can also be used when
+ creating new certificates, CRLs, or OCSP requests and responses to encode
+ extensions that ``cryptography`` does not know how to generate.
.. attribute:: oid
@@ -2441,6 +2529,18 @@ X.509 Extensions
:param list policies: A list of :class:`PolicyInformation` instances.
+ As an example of how ``CertificatePolicies`` might be used, if you wanted
+ to check if a certificated contained the CAB Forum's "domain-validated"
+ policy, you might write code like:
+
+ .. code-block:: python
+
+ def contains_domain_validated(policies):
+ return any(
+ policy.oid.dotted_string == "2.23.140.1.2.1"
+ for policy in policies
+ )
+
.. attribute:: oid
.. versionadded:: 1.0
@@ -2752,6 +2852,12 @@ instances. The following common OIDs are available as constants.
Corresponds to the dotted string ``"2.5.4.17"``.
+ .. attribute:: UNSTRUCTURED_NAME
+
+ .. versionadded:: 3.0
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.9.2"``.
+
.. class:: SignatureAlgorithmOID
@@ -2836,6 +2942,20 @@ instances. The following common OIDs are available as constants.
Corresponds to the dotted string ``"2.16.840.1.101.3.4.3.2"``. This is
a SHA256 digest signed by a DSA key.
+ .. attribute:: ED25519
+
+ .. versionadded:: 2.8
+
+ Corresponds to the dotted string ``"1.3.101.112"``. This is a signature
+ using an ed25519 key.
+
+ .. attribute:: ED448
+
+ .. versionadded:: 2.8
+
+ Corresponds to the dotted string ``"1.3.101.113"``. This is a signature
+ using an ed448 key.
+
.. class:: ExtendedKeyUsageOID
@@ -2878,7 +2998,12 @@ instances. The following common OIDs are available as constants.
.. versionadded:: 2.0
Corresponds to the dotted string ``"2.5.29.37.0"``. This is used to
- denote that a certificate may be used for _any_ purposes.
+ denote that a certificate may be used for _any_ purposes. However,
+ :rfc:`5280` additionally notes that applications that require the
+ presence of a particular purpose _MAY_ reject certificates that include
+ the ``anyExtendedKeyUsage`` OID but not the particular OID expected for
+ the application. Therefore, the presence of this OID does not mean a
+ given application will accept the certificate for all purposes.
.. class:: AuthorityInformationAccessOID
@@ -2898,6 +3023,17 @@ instances. The following common OIDs are available as constants.
:class:`~cryptography.x509.AccessDescription` objects.
+.. class:: SubjectInformationAccessOID
+
+ .. versionadded:: 3.0
+
+ .. attribute:: CA_REPOSITORY
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.5"``. Used as the
+ identifier for CA repository data in
+ :class:`~cryptography.x509.AccessDescription` objects.
+
+
.. class:: CertificatePoliciesOID
.. versionadded:: 1.0
@@ -2975,6 +3111,14 @@ instances. The following common OIDs are available as constants.
for the :class:`~cryptography.x509.AuthorityInformationAccess` extension
type.
+ .. attribute:: SUBJECT_INFORMATION_ACCESS
+
+ .. versionadded:: 3.0
+
+ Corresponds to the dotted string ``"1.3.6.1.5.5.7.1.11"``. The
+ identifier for the :class:`~cryptography.x509.SubjectInformationAccess`
+ extension type.
+
.. attribute:: INHIBIT_ANY_POLICY
Corresponds to the dotted string ``"2.5.29.54"``. The identifier
@@ -3018,6 +3162,12 @@ instances. The following common OIDs are available as constants.
Corresponds to the dotted string ``"1.3.6.1.4.1.11129.2.4.3"``.
+ .. attribute:: SIGNED_CERTIFICATE_TIMESTAMPS
+
+ .. versionadded:: 3.0
+
+ Corresponds to the dotted string ``"1.3.6.1.4.1.11129.2.4.5"``.
+
.. attribute:: POLICY_CONSTRAINTS
Corresponds to the dotted string ``"2.5.29.36"``. The identifier for the
@@ -3060,6 +3210,19 @@ instances. The following common OIDs are available as constants.
Corresponds to the dotted string ``"1.3.6.1.5.5.7.48.1.2"``.
+
+.. class:: AttributeOID
+
+ .. versionadded:: 3.0
+
+ .. attribute:: CHALLENGE_PASSWORD
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.9.7"``.
+
+ .. attribute:: UNSTRUCTURED_NAME
+
+ Corresponds to the dotted string ``"1.2.840.113549.1.9.2"``.
+
Helper Functions
~~~~~~~~~~~~~~~~
.. currentmodule:: cryptography.x509
@@ -3107,6 +3270,18 @@ Exceptions
Returns the OID.
+.. class:: AttributeNotFound
+
+ This is raised when calling
+ :meth:`CertificateSigningRequest.get_attribute_for_oid` with
+ an attribute OID that is not present in the request.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns the OID.
+
.. class:: UnsupportedGeneralNameType
This is raised when a certificate contains an unsupported general name
diff --git a/docs/x509/tutorial.rst b/docs/x509/tutorial.rst
index d34b35043..f5ca416ce 100644
--- a/docs/x509/tutorial.rst
+++ b/docs/x509/tutorial.rst
@@ -27,14 +27,12 @@ are the most common types of keys on the web right now):
.. code-block:: pycon
- >>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import serialization
>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> # Generate our key
>>> key = rsa.generate_private_key(
... public_exponent=65537,
... key_size=2048,
- ... backend=default_backend()
... )
>>> # Write our key to disk for safe keeping
>>> with open("path/to/store/key.pem", "wb") as f:
@@ -63,7 +61,7 @@ a few details:
>>> csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
... # Provide various details about who we are.
... x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- ... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"CA"),
+ ... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"),
... x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
... x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
... x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
@@ -76,7 +74,7 @@ a few details:
... ]),
... critical=False,
... # Sign the CSR with our private key.
- ... ).sign(key, hashes.SHA256(), default_backend())
+ ... ).sign(key, hashes.SHA256())
>>> # Write our CSR out to disk.
>>> with open("path/to/csr.pem", "wb") as f:
... f.write(csr.public_bytes(serialization.Encoding.PEM))
@@ -105,7 +103,6 @@ Like generating a CSR, we start with creating a new private key:
>>> key = rsa.generate_private_key(
... public_exponent=65537,
... key_size=2048,
- ... backend=default_backend()
... )
>>> # Write our key to disk for safe keeping
>>> with open("path/to/store/key.pem", "wb") as f:
@@ -123,7 +120,7 @@ Then we generate the certificate itself:
>>> # subject and issuer are always the same.
>>> subject = issuer = x509.Name([
... x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- ... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"CA"),
+ ... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"),
... x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
... x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
... x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
@@ -145,7 +142,7 @@ Then we generate the certificate itself:
... x509.SubjectAlternativeName([x509.DNSName(u"localhost")]),
... critical=False,
... # Sign our certificate with our private key
- ... ).sign(key, hashes.SHA256(), default_backend())
+ ... ).sign(key, hashes.SHA256())
>>> # Write our certificate out to disk.
>>> with open("path/to/certificate.pem", "wb") as f:
... f.write(cert.public_bytes(serialization.Encoding.PEM))
diff --git a/pyproject.toml b/pyproject.toml
index 7d64f993a..667f29e23 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,14 @@
[build-system]
-# Must be kept in sync with `setup_requirements` in `setup.py`
requires = [
- "setuptools>=18.5",
+ # The minimum setuptools version is specific to the PEP 517 backend,
+ # and may be stricter than the version required in `setup.py`
+ "setuptools>=40.6.0",
"wheel",
- "cffi>=1.8,!=1.11.3; python_implementation != 'PyPy'",
+ # Must be kept in sync with the `setup_requirements` in `setup.py`
+ "cffi>=1.12; platform_python_implementation != 'PyPy'",
]
+build-backend = "setuptools.build_meta"
+
+[tool.black]
+line-length = 79
+target-version = ["py27"]
diff --git a/release.py b/release.py
index d7c18d105..5f3f251d1 100644
--- a/release.py
+++ b/release.py
@@ -7,122 +7,136 @@ from __future__ import absolute_import, division, print_function
import getpass
import glob
import io
+import json
import os
import subprocess
import time
+import zipfile
import click
-from clint.textui.progress import Bar as ProgressBar
-
import requests
-JENKINS_URL = (
- "https://ci.cryptography.io/job/cryptography-support-jobs/"
- "job/wheel-builder"
-)
-
-
def run(*args, **kwargs):
print("[running] {0}".format(list(args)))
subprocess.check_call(list(args), **kwargs)
-def wait_for_build_completed(session):
- # Wait 20 seconds before actually checking if the build is complete, to
- # ensure that it had time to really start.
- time.sleep(20)
+def wait_for_build_complete_github_actions(session, token, run_url):
while True:
response = session.get(
- "{0}/lastBuild/api/json/".format(JENKINS_URL),
+ run_url,
headers={
- "Accept": "application/json",
- }
+ "Content-Type": "application/json",
+ "Authorization": "token {}".format(token),
+ },
)
response.raise_for_status()
- if not response.json()["building"]:
- assert response.json()["result"] == "SUCCESS"
+ if response.json()["conclusion"] is not None:
break
- time.sleep(0.1)
+ time.sleep(3)
-def download_artifacts(session):
+def download_artifacts_github_actions(session, token, run_url):
response = session.get(
- "{0}/lastBuild/api/json/".format(JENKINS_URL),
+ run_url,
headers={
- "Accept": "application/json"
- }
+ "Content-Type": "application/json",
+ "Authorization": "token {}".format(token),
+ },
)
response.raise_for_status()
- json_response = response.json()
- assert not json_response["building"]
- assert json_response["result"] == "SUCCESS"
+ response = session.get(
+ response.json()["artifacts_url"],
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": "token {}".format(token),
+ },
+ )
+ response.raise_for_status()
paths = []
-
- for artifact in json_response["artifacts"]:
+ for artifact in response.json()["artifacts"]:
response = session.get(
- "{0}artifact/{1}".format(
- json_response["url"], artifact["relativePath"]
- ), stream=True
- )
- assert response.headers["content-length"]
- print("Downloading {0}".format(artifact["fileName"]))
- bar = ProgressBar(
- expected_size=int(response.headers["content-length"]),
- filled_char="="
- )
- content = io.BytesIO()
- for data in response.iter_content(chunk_size=8192):
- content.write(data)
- bar.show(content.tell())
- assert bar.expected_size == content.tell()
- bar.done()
- out_path = os.path.join(
- os.path.dirname(__file__),
- "dist",
- artifact["fileName"],
+ artifact["archive_download_url"],
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": "token {}".format(token),
+ },
)
- with open(out_path, "wb") as f:
- f.write(content.getvalue())
- paths.append(out_path)
+ with zipfile.ZipFile(io.BytesIO(response.content)) as z:
+ for name in z.namelist():
+ if not name.endswith(".whl"):
+ continue
+ p = z.open(name)
+ out_path = os.path.join(
+ os.path.dirname(__file__),
+ "dist",
+ os.path.basename(name),
+ )
+ with open(out_path, "wb") as f:
+ f.write(p.read())
+ paths.append(out_path)
return paths
+def build_github_actions_wheels(token, version):
+ session = requests.Session()
+
+ response = session.post(
+ "https://api.github.com/repos/pyca/cryptography/actions/workflows/"
+ "wheel-builder.yml/dispatches",
+ headers={
+ "Content-Type": "application/json",
+ "Accept": "application/vnd.github.v3+json",
+ "Authorization": "token {}".format(token),
+ },
+ data=json.dumps({"ref": "master", "inputs": {"version": version}}),
+ )
+ response.raise_for_status()
+
+ # Give it a few seconds for the run to kick off.
+ time.sleep(5)
+ response = session.get(
+ (
+ "https://api.github.com/repos/pyca/cryptography/actions/workflows/"
+ "wheel-builder.yml/runs?event=workflow_dispatch"
+ ),
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": "token {}".format(token),
+ },
+ )
+ response.raise_for_status()
+ run_url = response.json()["workflow_runs"][0]["url"]
+ wait_for_build_complete_github_actions(session, token, run_url)
+ return download_artifacts_github_actions(session, token, run_url)
+
+
@click.command()
@click.argument("version")
def release(version):
"""
``version`` should be a string like '0.4' or '1.0'.
"""
+ github_token = getpass.getpass("Github person access token: ")
+
run("git", "tag", "-s", version, "-m", "{0} release".format(version))
run("git", "push", "--tags")
run("python", "setup.py", "sdist")
run("python", "setup.py", "sdist", "bdist_wheel", cwd="vectors/")
- packages = (
- glob.glob("dist/cryptography-{0}*".format(version)) +
- glob.glob("vectors/dist/cryptography_vectors-{0}*".format(version))
+ packages = glob.glob("dist/cryptography-{0}*".format(version)) + glob.glob(
+ "vectors/dist/cryptography_vectors-{0}*".format(version)
)
run("twine", "upload", "-s", *packages)
- session = requests.Session()
-
- token = getpass.getpass("Input the Jenkins token: ")
- response = session.get(
- "{0}/buildWithParameters".format(JENKINS_URL),
- params={
- "token": token,
- "BUILD_VERSION": version,
- "cause": "Building wheels for {0}".format(version)
- }
+ github_actions_wheel_paths = build_github_actions_wheels(
+ github_token, version
)
- response.raise_for_status()
- wait_for_build_completed(session)
- paths = download_artifacts(session)
- run("twine", "upload", *paths)
+ run("twine", "upload", *github_actions_wheel_paths)
if __name__ == "__main__":
diff --git a/setup.py b/setup.py
index 5b29d32e6..4ebbc1b50 100644
--- a/setup.py
+++ b/setup.py
@@ -8,26 +8,10 @@ from __future__ import absolute_import, division, print_function
import os
import platform
-import subprocess
import sys
-from distutils.command.build import build
-import pkg_resources
-
-import setuptools
from setuptools import find_packages, setup
-from setuptools.command.install import install
-from setuptools.command.test import test
-
-if (
- pkg_resources.parse_version(setuptools.__version__) <
- pkg_resources.parse_version("18.5")
-):
- raise RuntimeError(
- "cryptography requires setuptools 18.5 or newer, please upgrade to a "
- "newer version of setuptools"
- )
base_dir = os.path.dirname(__file__)
src_dir = os.path.join(base_dir, "src")
@@ -38,13 +22,11 @@ sys.path.insert(0, src_dir)
about = {}
with open(os.path.join(src_dir, "cryptography", "__about__.py")) as f:
- exec(f.read(), about)
-
+ exec (f.read(), about)
-VECTORS_DEPENDENCY = "cryptography_vectors=={0}".format(about['__version__'])
# `setup_requirements` must be kept in sync with `pyproject.toml`
-setup_requirements = ["cffi>=1.8,!=1.11.3"]
+setup_requirements = ["cffi>=1.12"]
if platform.python_implementation() == "PyPy":
if sys.pypy_version_info < (5, 4):
@@ -53,273 +35,112 @@ if platform.python_implementation() == "PyPy":
"PyPy to use this library."
)
-test_requirements = [
- "pytest>=3.6.0,!=3.9.0,!=3.9.1,!=3.9.2",
- "pretend",
- "iso8601",
- "pytz",
- "hypothesis>=1.11.4,!=3.79.2",
-]
-
-
-# If there's no vectors locally that probably means we are in a tarball and
-# need to go and get the matching vectors package from PyPi
-if not os.path.exists(os.path.join(base_dir, "vectors/setup.py")):
- test_requirements.append(VECTORS_DEPENDENCY)
-
-
-class PyTest(test):
- def finalize_options(self):
- test.finalize_options(self)
- self.test_args = []
- self.test_suite = True
-
- # This means there's a vectors/ folder with the package in here.
- # cd into it, install the vectors package and then refresh sys.path
- if VECTORS_DEPENDENCY not in test_requirements:
- subprocess.check_call(
- [sys.executable, "setup.py", "install"], cwd="vectors"
- )
- pkg_resources.get_distribution("cryptography_vectors").activate()
-
- def run_tests(self):
- # Import here because in module scope the eggs are not loaded.
- import pytest
- test_args = [os.path.join(base_dir, "tests")]
- errno = pytest.main(test_args)
- sys.exit(errno)
-
-
-def keywords_with_side_effects(argv):
- """
- Get a dictionary with setup keywords that (can) have side effects.
-
- :param argv: A list of strings with command line arguments.
- :returns: A dictionary with keyword arguments for the ``setup()`` function.
-
- This setup.py script uses the setuptools 'setup_requires' feature because
- this is required by the cffi package to compile extension modules. The
- purpose of ``keywords_with_side_effects()`` is to avoid triggering the cffi
- build process as a result of setup.py invocations that don't need the cffi
- module to be built (setup.py serves the dual purpose of exposing package
- metadata).
-
- All of the options listed by ``python setup.py --help`` that print
- information should be recognized here. The commands ``clean``,
- ``egg_info``, ``register``, ``sdist`` and ``upload`` are also recognized.
- Any combination of these options and commands is also supported.
-
- This function was originally based on the `setup.py script`_ of SciPy (see
- also the discussion in `pip issue #25`_).
-
- .. _pip issue #25: https://github.com/pypa/pip/issues/25
- .. _setup.py script: https://github.com/scipy/scipy/blob/master/setup.py
- """
- no_setup_requires_arguments = (
- '-h', '--help',
- '-n', '--dry-run',
- '-q', '--quiet',
- '-v', '--verbose',
- '-V', '--version',
- '--author',
- '--author-email',
- '--classifiers',
- '--contact',
- '--contact-email',
- '--description',
- '--egg-base',
- '--fullname',
- '--help-commands',
- '--keywords',
- '--licence',
- '--license',
- '--long-description',
- '--maintainer',
- '--maintainer-email',
- '--name',
- '--no-user-cfg',
- '--obsoletes',
- '--platforms',
- '--provides',
- '--requires',
- '--url',
- 'clean',
- 'egg_info',
- 'register',
- 'sdist',
- 'upload',
- )
-
- def is_short_option(argument):
- """Check whether a command line argument is a short option."""
- return len(argument) >= 2 and argument[0] == '-' and argument[1] != '-'
-
- def expand_short_options(argument):
- """Expand combined short options into canonical short options."""
- return ('-' + char for char in argument[1:])
-
- def argument_without_setup_requirements(argv, i):
- """Check whether a command line argument needs setup requirements."""
- if argv[i] in no_setup_requires_arguments:
- # Simple case: An argument which is either an option or a command
- # which doesn't need setup requirements.
- return True
- elif (is_short_option(argv[i]) and
- all(option in no_setup_requires_arguments
- for option in expand_short_options(argv[i]))):
- # Not so simple case: Combined short options none of which need
- # setup requirements.
- return True
- elif argv[i - 1:i] == ['--egg-base']:
- # Tricky case: --egg-info takes an argument which should not make
- # us use setup_requires (defeating the purpose of this code).
- return True
- else:
- return False
-
- if all(argument_without_setup_requirements(argv, i)
- for i in range(1, len(argv))):
- return {
- "cmdclass": {
- "build": DummyBuild,
- "install": DummyInstall,
- "test": DummyPyTest,
- }
- }
- else:
- cffi_modules = [
- "src/_cffi_src/build_openssl.py:ffi",
- "src/_cffi_src/build_constant_time.py:ffi",
- "src/_cffi_src/build_padding.py:ffi",
- ]
-
- return {
- "setup_requires": setup_requirements,
- "cmdclass": {
- "test": PyTest,
- },
- "cffi_modules": cffi_modules
- }
-
-
-setup_requires_error = ("Requested setup command that needs 'setup_requires' "
- "while command line arguments implied a side effect "
- "free command or option.")
-
-
-class DummyBuild(build):
- """
- This class makes it very obvious when ``keywords_with_side_effects()`` has
- incorrectly interpreted the command line arguments to ``setup.py build`` as
- one of the 'side effect free' commands or options.
- """
-
- def run(self):
- raise RuntimeError(setup_requires_error)
-
-
-class DummyInstall(install):
- """
- This class makes it very obvious when ``keywords_with_side_effects()`` has
- incorrectly interpreted the command line arguments to ``setup.py install``
- as one of the 'side effect free' commands or options.
- """
-
- def run(self):
- raise RuntimeError(setup_requires_error)
-
-
-class DummyPyTest(test):
- """
- This class makes it very obvious when ``keywords_with_side_effects()`` has
- incorrectly interpreted the command line arguments to ``setup.py test`` as
- one of the 'side effect free' commands or options.
- """
-
- def run_tests(self):
- raise RuntimeError(setup_requires_error)
-
with open(os.path.join(base_dir, "README.rst")) as f:
long_description = f.read()
-setup(
- name=about["__title__"],
- version=about["__version__"],
-
- description=about["__summary__"],
- long_description=long_description,
- license=about["__license__"],
- url=about["__uri__"],
-
- author=about["__author__"],
- author_email=about["__email__"],
-
- classifiers=[
- "Development Status :: 5 - Production/Stable",
- "Intended Audience :: Developers",
- "License :: OSI Approved :: Apache Software License",
- "License :: OSI Approved :: BSD License",
- "Natural Language :: English",
- "Operating System :: MacOS :: MacOS X",
- "Operating System :: POSIX",
- "Operating System :: POSIX :: BSD",
- "Operating System :: POSIX :: Linux",
- "Operating System :: Microsoft :: Windows",
- "Programming Language :: Python",
- "Programming Language :: Python :: 2",
- "Programming Language :: Python :: 2.7",
- "Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.4",
- "Programming Language :: Python :: 3.5",
- "Programming Language :: Python :: 3.6",
- "Programming Language :: Python :: 3.7",
- "Programming Language :: Python :: Implementation :: CPython",
- "Programming Language :: Python :: Implementation :: PyPy",
- "Topic :: Security :: Cryptography",
- ],
-
- package_dir={"": "src"},
- packages=find_packages(where="src", exclude=["_cffi_src", "_cffi_src.*"]),
- include_package_data=True,
-
- python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
-
- install_requires=[
- "asn1crypto >= 0.21.0",
- "six >= 1.4.1",
- ] + setup_requirements,
- tests_require=test_requirements,
- extras_require={
- ":python_version < '3'": ["enum34", "ipaddress"],
-
- "test": test_requirements,
- "docs": [
- "sphinx >= 1.6.5,!=1.8.0",
- "sphinx_rtd_theme",
+try:
+ setup(
+ name=about["__title__"],
+ version=about["__version__"],
+ description=about["__summary__"],
+ long_description=long_description,
+ long_description_content_type="text/x-rst",
+ license=about["__license__"],
+ url=about["__uri__"],
+ author=about["__author__"],
+ author_email=about["__email__"],
+ classifiers=[
+ "Development Status :: 5 - Production/Stable",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: Apache Software License",
+ "License :: OSI Approved :: BSD License",
+ "Natural Language :: English",
+ "Operating System :: MacOS :: MacOS X",
+ "Operating System :: POSIX",
+ "Operating System :: POSIX :: BSD",
+ "Operating System :: POSIX :: Linux",
+ "Operating System :: Microsoft :: Windows",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: Implementation :: CPython",
+ "Programming Language :: Python :: Implementation :: PyPy",
+ "Topic :: Security :: Cryptography",
],
- "docstest": [
- "doc8",
- "pyenchant >= 1.6.11",
- "twine >= 1.12.0",
- "sphinxcontrib-spelling >= 4.0.1",
- ],
- "pep8test": [
- "flake8",
- "flake8-import-order",
- "pep8-naming",
+ package_dir={"": "src"},
+ packages=find_packages(
+ where="src", exclude=["_cffi_src", "_cffi_src.*"]
+ ),
+ include_package_data=True,
+ python_requires=(
+ ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*"
+ ),
+ install_requires=["six >= 1.4.1"] + setup_requirements,
+ setup_requires=setup_requirements,
+ extras_require={
+ ":python_version < '3'": ["enum34", "ipaddress"],
+ "test": [
+ "pytest>=3.6.0,!=3.9.0,!=3.9.1,!=3.9.2",
+ "pretend",
+ "iso8601",
+ "pytz",
+ "hypothesis>=1.11.4,!=3.79.2",
+ ],
+ "docs": [
+ "sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1",
+ "sphinx_rtd_theme",
+ ],
+ "docstest": [
+ "doc8",
+ "pyenchant >= 1.6.11",
+ "twine >= 1.12.0",
+ "sphinxcontrib-spelling >= 4.0.1",
+ ],
+ "pep8test": [
+ "black",
+ "flake8",
+ "flake8-import-order",
+ "pep8-naming",
+ ],
+ # This extra is for OpenSSH private keys that use bcrypt KDF
+ # Versions: v3.1.3 - ignore_few_rounds, v3.1.5 - abi3
+ "ssh": ["bcrypt >= 3.1.5"],
+ },
+ # for cffi
+ zip_safe=False,
+ ext_package="cryptography.hazmat.bindings",
+ cffi_modules=[
+ "src/_cffi_src/build_openssl.py:ffi",
+ "src/_cffi_src/build_padding.py:ffi",
],
- # This extra is for the U-label support that was deprecated in
- # cryptography 2.1. If you need this deprecated path install with
- # pip install cryptography[idna]
- "idna": [
- "idna >= 2.1",
- ]
- },
-
- # for cffi
- zip_safe=False,
- ext_package="cryptography.hazmat.bindings",
- **keywords_with_side_effects(sys.argv)
-)
+ )
+except: # noqa: E722
+ # Note: This is a bare exception that re-raises so that we don't interfere
+ # with anything the installation machinery might want to do. Because we
+ # print this for any exception this msg can appear (e.g. in verbose logs)
+ # even if there's no failure. For example, SetupRequirementsError is raised
+ # during PEP517 building and prints this text. setuptools raises SystemExit
+ # when compilation fails right now, but it's possible this isn't stable
+ # or a public API commitment so we'll remain ultra conservative.
+ print(
+ """
+ =============================DEBUG ASSISTANCE=============================
+ If you are seeing a compilation error please try the following steps to
+ successfully install cryptography:
+ 1) Upgrade to the latest pip and try again. This will fix errors for most
+ users. See: https://pip.pypa.io/en/stable/installing/#upgrading-pip
+ 2) Read https://cryptography.io/en/latest/installation.html for specific
+ instructions for your platform.
+ 3) Check our frequently asked questions for more information:
+ https://cryptography.io/en/latest/faq.html
+ =============================DEBUG ASSISTANCE=============================
+ """
+ )
+ raise
diff --git a/src/_cffi_src/build_constant_time.py b/src/_cffi_src/build_constant_time.py
deleted file mode 100644
index 7a11f7b58..000000000
--- a/src/_cffi_src/build_constant_time.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-from __future__ import absolute_import, division, print_function
-
-import os
-
-from _cffi_src.utils import build_ffi, compiler_type, extra_link_args
-
-
-with open(os.path.join(
- os.path.dirname(__file__), "hazmat_src/constant_time.h"
-)) as f:
- types = f.read()
-
-with open(os.path.join(
- os.path.dirname(__file__), "hazmat_src/constant_time.c"
-)) as f:
- functions = f.read()
-
-ffi = build_ffi(
- module_name="_constant_time",
- cdef_source=types,
- verify_source=functions,
- extra_link_args=extra_link_args(compiler_type()),
-)
diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py
index 456b86926..4380c3396 100644
--- a/src/_cffi_src/build_openssl.py
+++ b/src/_cffi_src/build_openssl.py
@@ -6,9 +6,14 @@ from __future__ import absolute_import, division, print_function
import os
import sys
+from distutils import dist
+from distutils.ccompiler import get_default_compiler
+from distutils.command.config import config
from _cffi_src.utils import (
- build_ffi_for_binding, compiler_type, extra_link_args
+ build_ffi_for_binding,
+ compiler_type,
+ extra_link_args,
)
@@ -17,23 +22,28 @@ def _get_openssl_libraries(platform):
return []
# OpenSSL goes by a different library name on different operating systems.
if platform == "win32" and compiler_type() == "msvc":
- windows_link_legacy_openssl = os.environ.get(
- "CRYPTOGRAPHY_WINDOWS_LINK_LEGACY_OPENSSL", None
- )
- if windows_link_legacy_openssl is None:
- # Link against the 1.1.0 names
- libs = ["libssl", "libcrypto"]
- else:
- # Link against the 1.0.2 and lower names
- libs = ["libeay32", "ssleay32"]
- return libs + ["advapi32", "crypt32", "gdi32", "user32", "ws2_32"]
+ return [
+ "libssl",
+ "libcrypto",
+ "advapi32",
+ "crypt32",
+ "gdi32",
+ "user32",
+ "ws2_32",
+ ]
else:
# darwin, linux, mingw all use this path
# In some circumstances, the order in which these libs are
# specified on the linker command-line is significant;
# libssl must come before libcrypto
# (https://marc.info/?l=openssl-users&m=135361825921871)
- return ["ssl", "crypto"]
+ # -lpthread required due to usage of pthread an potential
+ # existance of a static part containing e.g. pthread_atfork
+ # (https://github.com/pyca/cryptography/issues/5084)
+ if sys.platform == "zos":
+ return ["ssl", "crypto"]
+ else:
+ return ["ssl", "crypto", "pthread"]
def _extra_compile_args(platform):
@@ -41,12 +51,24 @@ def _extra_compile_args(platform):
We set -Wconversion args here so that we only do Wconversion checks on the
code we're compiling and not on cffi itself (as passing -Wconversion in
CFLAGS would do). We set no error on sign conversion because some
- function signatures in OpenSSL have changed from long -> unsigned long
- in the past. Since that isn't a precision issue we don't care.
- When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 we can
- revisit this.
+ function signatures in LibreSSL differ from OpenSSL have changed on long
+ vs. unsigned long in the past. Since that isn't a precision issue we don't
+ care.
"""
- if platform not in ["win32", "hp-ux11", "sunos5"]:
+ # make sure the compiler used supports the flags to be added
+ is_gcc = False
+ if get_default_compiler() == "unix":
+ d = dist.Distribution()
+ cmd = config(d)
+ cmd._check_compiler()
+ is_gcc = (
+ "gcc" in cmd.compiler.compiler[0]
+ or "clang" in cmd.compiler.compiler[0]
+ )
+ if is_gcc or not (
+ platform in ["win32", "hp-ux11", "sunos5"]
+ or platform.startswith("aix")
+ ):
return ["-Wconversion", "-Wno-error=sign-conversion"]
else:
return []
@@ -58,7 +80,6 @@ ffi = build_ffi_for_binding(
modules=[
# This goes first so we can define some cryptography-wide symbols.
"cryptography",
-
"aes",
"asn1",
"bignum",
@@ -95,13 +116,6 @@ ffi = build_ffi_for_binding(
"callbacks",
],
libraries=_get_openssl_libraries(sys.platform),
- # These args are passed here so that we only do Wconversion checks on the
- # code we're compiling and not on cffi itself (as passing -Wconversion in
- # CFLAGS would do). We set no error on sign convesrion because some
- # function signatures in OpenSSL have changed from long -> unsigned long
- # in the past. Since that isn't a precision issue we don't care.
- # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 we can
- # revisit this.
extra_compile_args=_extra_compile_args(sys.platform),
extra_link_args=extra_link_args(compiler_type()),
)
diff --git a/src/_cffi_src/build_padding.py b/src/_cffi_src/build_padding.py
index 4c5096a19..207f4a658 100644
--- a/src/_cffi_src/build_padding.py
+++ b/src/_cffi_src/build_padding.py
@@ -9,14 +9,14 @@ import os
from _cffi_src.utils import build_ffi, compiler_type, extra_link_args
-with open(os.path.join(
- os.path.dirname(__file__), "hazmat_src/padding.h"
-)) as f:
+with open(
+ os.path.join(os.path.dirname(__file__), "hazmat_src/padding.h")
+) as f:
types = f.read()
-with open(os.path.join(
- os.path.dirname(__file__), "hazmat_src/padding.c"
-)) as f:
+with open(
+ os.path.join(os.path.dirname(__file__), "hazmat_src/padding.c")
+) as f:
functions = f.read()
ffi = build_ffi(
diff --git a/src/_cffi_src/hazmat_src/constant_time.c b/src/_cffi_src/hazmat_src/constant_time.c
deleted file mode 100644
index 0a48fe83a..000000000
--- a/src/_cffi_src/hazmat_src/constant_time.c
+++ /dev/null
@@ -1,22 +0,0 @@
-// This file is dual licensed under the terms of the Apache License, Version
-// 2.0, and the BSD License. See the LICENSE file in the root of this
-// repository for complete details.
-
-uint8_t Cryptography_constant_time_bytes_eq(uint8_t *a, size_t len_a,
- uint8_t *b, size_t len_b) {
- size_t i = 0;
- uint8_t mismatch = 0;
- if (len_a != len_b) {
- return 0;
- }
- for (i = 0; i < len_a; i++) {
- mismatch |= a[i] ^ b[i];
- }
-
- /* Make sure any bits set are copied to the lowest bit */
- mismatch |= mismatch >> 4;
- mismatch |= mismatch >> 2;
- mismatch |= mismatch >> 1;
- /* Now check the low bit to see if it's set */
- return (mismatch & 1) == 0;
-}
diff --git a/src/_cffi_src/hazmat_src/constant_time.h b/src/_cffi_src/hazmat_src/constant_time.h
deleted file mode 100644
index 593479f66..000000000
--- a/src/_cffi_src/hazmat_src/constant_time.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// This file is dual licensed under the terms of the Apache License, Version
-// 2.0, and the BSD License. See the LICENSE file in the root of this
-// repository for complete details.
-
-uint8_t Cryptography_constant_time_bytes_eq(uint8_t *, size_t, uint8_t *,
- size_t);
diff --git a/src/_cffi_src/openssl/aes.py b/src/_cffi_src/openssl/aes.py
index 028c92ce2..25ef3ec0e 100644
--- a/src/_cffi_src/openssl/aes.py
+++ b/src/_cffi_src/openssl/aes.py
@@ -9,18 +9,10 @@ INCLUDES = """
"""
TYPES = """
-static const int Cryptography_HAS_AES_WRAP;
-
-struct aes_key_st {
- ...;
-};
-typedef struct aes_key_st AES_KEY;
+typedef ... AES_KEY;
"""
FUNCTIONS = """
-int AES_set_encrypt_key(const unsigned char *, const int, AES_KEY *);
-int AES_set_decrypt_key(const unsigned char *, const int, AES_KEY *);
-
int AES_wrap_key(AES_KEY *, const unsigned char *, unsigned char *,
const unsigned char *, unsigned int);
int AES_unwrap_key(AES_KEY *, const unsigned char *, unsigned char *,
@@ -28,5 +20,4 @@ int AES_unwrap_key(AES_KEY *, const unsigned char *, unsigned char *,
"""
CUSTOMIZATIONS = """
-static const long Cryptography_HAS_AES_WRAP = 1;
"""
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py
index 82bf79792..da55b670e 100644
--- a/src/_cffi_src/openssl/asn1.py
+++ b/src/_cffi_src/openssl/asn1.py
@@ -27,7 +27,10 @@ typedef struct asn1_string_st ASN1_TIME;
typedef ... ASN1_OBJECT;
typedef struct asn1_string_st ASN1_STRING;
typedef struct asn1_string_st ASN1_UTF8STRING;
-typedef ... ASN1_TYPE;
+typedef struct {
+ int type;
+ ...;
+} ASN1_TYPE;
typedef ... ASN1_GENERALIZEDTIME;
typedef ... ASN1_ENUMERATED;
typedef ... ASN1_NULL;
@@ -59,7 +62,6 @@ int ASN1_INTEGER_set(ASN1_INTEGER *, long);
/* ASN1 TIME */
ASN1_TIME *ASN1_TIME_new(void);
void ASN1_TIME_free(ASN1_TIME *);
-ASN1_TIME *ASN1_TIME_set(ASN1_TIME *, time_t);
int ASN1_TIME_set_string(ASN1_TIME *, const char *);
/* ASN1 GENERALIZEDTIME */
diff --git a/src/_cffi_src/openssl/bignum.py b/src/_cffi_src/openssl/bignum.py
index a352f5a87..751018391 100644
--- a/src/_cffi_src/openssl/bignum.py
+++ b/src/_cffi_src/openssl/bignum.py
@@ -52,6 +52,7 @@ BIGNUM *BN_bin2bn(const unsigned char *, int, BIGNUM *);
int BN_num_bits(const BIGNUM *);
int BN_cmp(const BIGNUM *, const BIGNUM *);
+int BN_is_negative(const BIGNUM *);
int BN_add(BIGNUM *, const BIGNUM *, const BIGNUM *);
int BN_sub(BIGNUM *, const BIGNUM *, const BIGNUM *);
int BN_nnmod(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
diff --git a/src/_cffi_src/openssl/bio.py b/src/_cffi_src/openssl/bio.py
index d65775a09..52d57c622 100644
--- a/src/_cffi_src/openssl/bio.py
+++ b/src/_cffi_src/openssl/bio.py
@@ -15,6 +15,7 @@ typedef ... BIO_METHOD;
FUNCTIONS = """
int BIO_free(BIO *);
+void BIO_free_all(BIO *);
BIO *BIO_new_file(const char *, const char *);
BIO *BIO_new_dgram(int, int);
size_t BIO_ctrl_pending(BIO *);
@@ -40,10 +41,4 @@ void BIO_clear_retry_flags(BIO *);
"""
CUSTOMIZATIONS = """
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int BIO_up_ref(BIO *b) {
- CRYPTO_add(&b->references, 1, CRYPTO_LOCK_BIO);
- return 1;
-}
-#endif
"""
diff --git a/src/_cffi_src/openssl/callbacks.py b/src/_cffi_src/openssl/callbacks.py
index 75c620165..19301b973 100644
--- a/src/_cffi_src/openssl/callbacks.py
+++ b/src/_cffi_src/openssl/callbacks.py
@@ -5,21 +5,7 @@
from __future__ import absolute_import, division, print_function
INCLUDES = """
-#include <openssl/ssl.h>
-#include <openssl/x509.h>
-#include <openssl/x509_vfy.h>
-#include <openssl/crypto.h>
-
-#ifdef _WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#include <Wincrypt.h>
-#include <Winsock2.h>
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#include <pthread.h>
-#endif
+#include <string.h>
"""
TYPES = """
@@ -33,112 +19,10 @@ typedef struct {
"""
FUNCTIONS = """
-int Cryptography_setup_ssl_threads(void);
int Cryptography_pem_password_cb(char *, int, int, void *);
"""
CUSTOMIZATIONS = """
-/* This code is derived from the locking code found in the Python _ssl module's
- locking callback for OpenSSL.
-
- Copyright 2001-2016 Python Software Foundation; All Rights Reserved.
-
- It has been subsequently modified to use cross platform locking without
- using CPython APIs by Armin Rigo of the PyPy project.
-*/
-
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
-#ifdef _WIN32
-typedef CRITICAL_SECTION Cryptography_mutex;
-static __inline void cryptography_mutex_init(Cryptography_mutex *mutex) {
- InitializeCriticalSection(mutex);
-}
-static __inline void cryptography_mutex_lock(Cryptography_mutex *mutex) {
- EnterCriticalSection(mutex);
-}
-static __inline void cryptography_mutex_unlock(Cryptography_mutex *mutex) {
- LeaveCriticalSection(mutex);
-}
-#else
-typedef pthread_mutex_t Cryptography_mutex;
-#define ASSERT_STATUS(call) \
- if ((call) != 0) { \
- perror("Fatal error in callback initialization: " #call); \
- abort(); \
- }
-static inline void cryptography_mutex_init(Cryptography_mutex *mutex) {
-#if !defined(pthread_mutexattr_default)
-# define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
-#endif
- ASSERT_STATUS(pthread_mutex_init(mutex, pthread_mutexattr_default));
-}
-static inline void cryptography_mutex_lock(Cryptography_mutex *mutex) {
- ASSERT_STATUS(pthread_mutex_lock(mutex));
-}
-static inline void cryptography_mutex_unlock(Cryptography_mutex *mutex) {
- ASSERT_STATUS(pthread_mutex_unlock(mutex));
-}
-#endif
-
-
-static unsigned int _ssl_locks_count = 0;
-static Cryptography_mutex *_ssl_locks = NULL;
-
-static void _ssl_thread_locking_function(int mode, int n, const char *file,
- int line) {
- /* this function is needed to perform locking on shared data
- structures. (Note that OpenSSL uses a number of global data
- structures that will be implicitly shared whenever multiple
- threads use OpenSSL.) Multi-threaded applications will
- crash at random if it is not set.
-
- locking_function() must be able to handle up to
- CRYPTO_num_locks() different mutex locks. It sets the n-th
- lock if mode & CRYPTO_LOCK, and releases it otherwise.
-
- file and line are the file number of the function setting the
- lock. They can be useful for debugging.
- */
-
- if ((_ssl_locks == NULL) ||
- (n < 0) || ((unsigned)n >= _ssl_locks_count)) {
- return;
- }
-
- if (mode & CRYPTO_LOCK) {
- cryptography_mutex_lock(_ssl_locks + n);
- } else {
- cryptography_mutex_unlock(_ssl_locks + n);
- }
-}
-
-static void init_mutexes(void) {
- int i;
- for (i = 0; i < _ssl_locks_count; i++) {
- cryptography_mutex_init(_ssl_locks + i);
- }
-}
-
-
-int Cryptography_setup_ssl_threads(void) {
- if (_ssl_locks == NULL) {
- _ssl_locks_count = CRYPTO_num_locks();
- _ssl_locks = calloc(_ssl_locks_count, sizeof(Cryptography_mutex));
- if (_ssl_locks == NULL) {
- return 0;
- }
- init_mutexes();
- CRYPTO_set_locking_callback(_ssl_thread_locking_function);
-#ifndef _WIN32
- pthread_atfork(NULL, NULL, &init_mutexes);
-#endif
- }
- return 1;
-}
-#else
-int (*Cryptography_setup_ssl_threads)(void) = NULL;
-#endif
-
typedef struct {
char *password;
int length;
diff --git a/src/_cffi_src/openssl/cmac.py b/src/_cffi_src/openssl/cmac.py
index f976647f7..557abd1ca 100644
--- a/src/_cffi_src/openssl/cmac.py
+++ b/src/_cffi_src/openssl/cmac.py
@@ -11,7 +11,6 @@ INCLUDES = """
"""
TYPES = """
-static const int Cryptography_HAS_CMAC;
typedef ... CMAC_CTX;
"""
@@ -25,5 +24,4 @@ void CMAC_CTX_free(CMAC_CTX *);
"""
CUSTOMIZATIONS = """
-static const long Cryptography_HAS_CMAC = 1;
"""
diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py
index 03672d55e..6064a4eee 100644
--- a/src/_cffi_src/openssl/crypto.py
+++ b/src/_cffi_src/openssl/crypto.py
@@ -9,7 +9,6 @@ INCLUDES = """
"""
TYPES = """
-static const long Cryptography_HAS_LOCKING_CALLBACKS;
static const long Cryptography_HAS_MEM_FUNCTIONS;
static const long Cryptography_HAS_OPENSSL_CLEANUP;
@@ -23,28 +22,11 @@ static const int OPENSSL_CFLAGS;
static const int OPENSSL_BUILT_ON;
static const int OPENSSL_PLATFORM;
static const int OPENSSL_DIR;
-static const int CRYPTO_MEM_CHECK_ON;
-static const int CRYPTO_MEM_CHECK_OFF;
-static const int CRYPTO_MEM_CHECK_ENABLE;
-static const int CRYPTO_MEM_CHECK_DISABLE;
-static const int CRYPTO_LOCK;
-static const int CRYPTO_UNLOCK;
-static const int CRYPTO_READ;
-static const int CRYPTO_LOCK_SSL;
"""
FUNCTIONS = """
-int CRYPTO_mem_ctrl(int);
-
-void CRYPTO_cleanup_all_ex_data(void);
void OPENSSL_cleanup(void);
-/* as of 1.1.0 OpenSSL does its own locking *angelic chorus*. These functions
- have become macros that are no ops */
-int CRYPTO_num_locks(void);
-void CRYPTO_set_locking_callback(void(*)(int, int, const char *, int));
-void (*CRYPTO_get_locking_callback(void))(int, int, const char *, int);
-
/* SSLeay was removed in 1.1.0 */
unsigned long SSLeay(void);
const char *SSLeay_version(int);
@@ -56,8 +38,6 @@ const char *OpenSSL_version(int);
void *OPENSSL_malloc(size_t);
void OPENSSL_free(void *);
-/* This was removed in 1.1.0 */
-void CRYPTO_lock(int, int, const char *, int);
/* Signature changed significantly in 1.1.0, only expose there for sanity */
int Cryptography_CRYPTO_set_mem_functions(
@@ -94,26 +74,8 @@ CUSTOMIZATIONS = """
# define OPENSSL_PLATFORM SSLEAY_PLATFORM
# define OPENSSL_DIR SSLEAY_DIR
#endif
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
-static const long Cryptography_HAS_LOCKING_CALLBACKS = 1;
-#else
-static const long Cryptography_HAS_LOCKING_CALLBACKS = 0;
-#if !defined(CRYPTO_LOCK)
-static const long CRYPTO_LOCK = 0;
-#endif
-#if !defined(CRYPTO_UNLOCK)
-static const long CRYPTO_UNLOCK = 0;
-#endif
-#if !defined(CRYPTO_READ)
-static const long CRYPTO_READ = 0;
-#endif
-#if !defined(CRYPTO_LOCK_SSL)
-static const long CRYPTO_LOCK_SSL = 0;
-#endif
-void (*CRYPTO_lock)(int, int, const char *, int) = NULL;
-#endif
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
static const long Cryptography_HAS_OPENSSL_CLEANUP = 0;
void (*OPENSSL_cleanup)(void) = NULL;
diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py
index e16fc57d9..f24bee5a4 100644
--- a/src/_cffi_src/openssl/cryptography.py
+++ b/src/_cffi_src/openssl/cryptography.py
@@ -33,38 +33,31 @@ INCLUDES = """
#include <Winsock2.h>
#endif
-#define CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER \
- (CRYPTOGRAPHY_IS_LIBRESSL && LIBRESSL_VERSION_NUMBER >= 0x2070000fL)
-
-#define CRYPTOGRAPHY_OPENSSL_102_OR_GREATER \
- (OPENSSL_VERSION_NUMBER >= 0x10002000 && !CRYPTOGRAPHY_IS_LIBRESSL)
-#define CRYPTOGRAPHY_OPENSSL_102L_OR_GREATER \
- (OPENSSL_VERSION_NUMBER >= 0x100020cf && !CRYPTOGRAPHY_IS_LIBRESSL)
-#define CRYPTOGRAPHY_OPENSSL_110_OR_GREATER \
- (OPENSSL_VERSION_NUMBER >= 0x10100000 && !CRYPTOGRAPHY_IS_LIBRESSL)
#define CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER \
(OPENSSL_VERSION_NUMBER >= 0x1010006f && !CRYPTOGRAPHY_IS_LIBRESSL)
-#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 \
- (OPENSSL_VERSION_NUMBER < 0x10002000 || CRYPTOGRAPHY_IS_LIBRESSL)
-#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I \
- (OPENSSL_VERSION_NUMBER < 0x1000209f || CRYPTOGRAPHY_IS_LIBRESSL)
-#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 \
- (OPENSSL_VERSION_NUMBER < 0x10100000 || CRYPTOGRAPHY_IS_LIBRESSL)
#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J \
(OPENSSL_VERSION_NUMBER < 0x101000af || CRYPTOGRAPHY_IS_LIBRESSL)
#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 \
(OPENSSL_VERSION_NUMBER < 0x10101000 || CRYPTOGRAPHY_IS_LIBRESSL)
+#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B \
+ (OPENSSL_VERSION_NUMBER < 0x10101020 || CRYPTOGRAPHY_IS_LIBRESSL)
+#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D \
+ (OPENSSL_VERSION_NUMBER < 0x10101040 || CRYPTOGRAPHY_IS_LIBRESSL)
+#if (CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D && !CRYPTOGRAPHY_IS_LIBRESSL && \
+ !defined(OPENSSL_NO_ENGINE)) || defined(USE_OSRANDOM_RNG_FOR_TESTING)
+#define CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE 1
+#else
+#define CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE 0
+#endif
"""
TYPES = """
-static const int CRYPTOGRAPHY_OPENSSL_102L_OR_GREATER;
-static const int CRYPTOGRAPHY_OPENSSL_110_OR_GREATER;
static const int CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER;
-static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I;
-static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_102;
static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111;
+static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B;
+static const int CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE;
static const int CRYPTOGRAPHY_IS_LIBRESSL;
"""
diff --git a/src/_cffi_src/openssl/ct.py b/src/_cffi_src/openssl/ct.py
index 71125dd17..5f0670635 100644
--- a/src/_cffi_src/openssl/ct.py
+++ b/src/_cffi_src/openssl/ct.py
@@ -5,7 +5,7 @@
from __future__ import absolute_import, division, print_function
INCLUDES = """
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+#if CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER && !defined(OPENSSL_NO_CT)
#include <openssl/ct.h>
typedef STACK_OF(SCT) Cryptography_STACK_OF_SCT;
@@ -50,13 +50,14 @@ uint64_t SCT_get_timestamp(const SCT *);
int SCT_set_source(SCT *, sct_source_t);
+Cryptography_STACK_OF_SCT *sk_SCT_new_null(void);
+void sk_SCT_free(Cryptography_STACK_OF_SCT *);
int sk_SCT_num(const Cryptography_STACK_OF_SCT *);
SCT *sk_SCT_value(const Cryptography_STACK_OF_SCT *, int);
+int sk_SCT_push(Cryptography_STACK_OF_SCT *, SCT *);
void SCT_LIST_free(Cryptography_STACK_OF_SCT *);
-int sk_SCT_push(Cryptography_STACK_OF_SCT *, SCT *);
-Cryptography_STACK_OF_SCT *sk_SCT_new_null(void);
SCT *SCT_new(void);
int SCT_set1_log_id(SCT *, unsigned char *, size_t);
void SCT_set_timestamp(SCT *, uint64_t);
@@ -65,7 +66,7 @@ int SCT_set_log_entry_type(SCT *, ct_log_entry_type_t);
"""
CUSTOMIZATIONS = """
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+#if CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER && !defined(OPENSSL_NO_CT)
static const long Cryptography_HAS_SCT = 1;
#else
static const long Cryptography_HAS_SCT = 0;
@@ -85,7 +86,12 @@ typedef enum {
SCT_SOURCE_X509V3_EXTENSION,
SCT_SOURCE_OCSP_STAPLED_RESPONSE
} sct_source_t;
+
+/* OpenSSL compiled with `no-ct` still defines the `SCT` struct. */
+#if !defined(OPENSSL_NO_CT)
typedef void SCT;
+#endif
+
typedef void Cryptography_STACK_OF_SCT;
sct_version_t (*SCT_get_version)(const SCT *) = NULL;
@@ -96,12 +102,13 @@ uint64_t (*SCT_get_timestamp)(const SCT *) = NULL;
int (*SCT_set_source)(SCT *, sct_source_t) = NULL;
+Cryptography_STACK_OF_SCT *(*sk_SCT_new_null)(void) = NULL;
+void (*sk_SCT_free)(Cryptography_STACK_OF_SCT *) = NULL;
int (*sk_SCT_num)(const Cryptography_STACK_OF_SCT *) = NULL;
SCT *(*sk_SCT_value)(const Cryptography_STACK_OF_SCT *, int) = NULL;
+int (*sk_SCT_push)(Cryptography_STACK_OF_SCT *, SCT *) = NULL;
void (*SCT_LIST_free)(Cryptography_STACK_OF_SCT *) = NULL;
-int (*sk_SCT_push)(Cryptography_STACK_OF_SCT *, SCT *) = NULL;
-Cryptography_STACK_OF_SCT *(*sk_SCT_new_null)(void) = NULL;
SCT *(*SCT_new)(void) = NULL;
int (*SCT_set1_log_id)(SCT *, unsigned char *, size_t) = NULL;
void (*SCT_set_timestamp)(SCT *, uint64_t) = NULL;
diff --git a/src/_cffi_src/openssl/dh.py b/src/_cffi_src/openssl/dh.py
index b0fd21f54..947a5a8ee 100644
--- a/src/_cffi_src/openssl/dh.py
+++ b/src/_cffi_src/openssl/dh.py
@@ -18,15 +18,8 @@ FUNCTIONS = """
DH *DH_new(void);
void DH_free(DH *);
int DH_size(const DH *);
-int DH_check_pub_key(const DH *, const BIGNUM *, int *);
int DH_generate_key(DH *);
int DH_compute_key(unsigned char *, const BIGNUM *, DH *);
-int DH_set_ex_data(DH *, int, void *);
-void *DH_get_ex_data(DH *, int);
-DH *d2i_DHparams(DH **, const unsigned char **, long);
-int i2d_DHparams(const DH *, unsigned char **);
-int DHparams_print_fp(FILE *, const DH *);
-int DHparams_print(BIO *, const DH *);
DH *DHparams_dup(DH *);
/* added in 1.1.0 when the DH struct was opaqued */
@@ -45,79 +38,7 @@ int Cryptography_i2d_DHxparams_bio(BIO *bp, DH *x);
"""
CUSTOMIZATIONS = """
-/* These functions were added in OpenSSL 1.1.0 */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-void DH_get0_pqg(const DH *dh,
- const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
-{
- if (p != NULL)
- *p = dh->p;
- if (q != NULL)
- *q = dh->q;
- if (g != NULL)
- *g = dh->g;
-}
-
-int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
-{
- /* If the fields p and g in d are NULL, the corresponding input
- * parameters MUST be non-NULL. q may remain NULL.
- */
- if ((dh->p == NULL && p == NULL)
- || (dh->g == NULL && g == NULL))
- return 0;
-
- if (p != NULL) {
- BN_free(dh->p);
- dh->p = p;
- }
- if (q != NULL) {
- BN_free(dh->q);
- dh->q = q;
- }
- if (g != NULL) {
- BN_free(dh->g);
- dh->g = g;
- }
-
- if (q != NULL) {
- dh->length = BN_num_bits(q);
- }
-
- return 1;
-}
-
-void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
-{
- if (pub_key != NULL)
- *pub_key = dh->pub_key;
- if (priv_key != NULL)
- *priv_key = dh->priv_key;
-}
-
-int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
-{
- /* If the field pub_key in dh is NULL, the corresponding input
- * parameters MUST be non-NULL. The priv_key field may
- * be left NULL.
- */
- if (dh->pub_key == NULL && pub_key == NULL)
- return 0;
-
- if (pub_key != NULL) {
- BN_free(dh->pub_key);
- dh->pub_key = pub_key;
- }
- if (priv_key != NULL) {
- BN_free(dh->priv_key);
- dh->priv_key = priv_key;
- }
-
- return 1;
-}
-#endif
-
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
#ifndef DH_CHECK_Q_NOT_PRIME
#define DH_CHECK_Q_NOT_PRIME 0x10
#endif
diff --git a/src/_cffi_src/openssl/dsa.py b/src/_cffi_src/openssl/dsa.py
index a4a87c366..3a290067b 100644
--- a/src/_cffi_src/openssl/dsa.py
+++ b/src/_cffi_src/openssl/dsa.py
@@ -34,70 +34,4 @@ int DSA_generate_parameters_ex(DSA *, int, unsigned char *, int,
"""
CUSTOMIZATIONS = """
-/* These functions were added in OpenSSL 1.1.0 */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-void DSA_get0_pqg(const DSA *d,
- const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
-{
- if (p != NULL)
- *p = d->p;
- if (q != NULL)
- *q = d->q;
- if (g != NULL)
- *g = d->g;
-}
-int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
-{
- /* If the fields p, q and g in d are NULL, the corresponding input
- * parameters MUST be non-NULL.
- */
- if ((d->p == NULL && p == NULL)
- || (d->q == NULL && q == NULL)
- || (d->g == NULL && g == NULL))
- return 0;
-
- if (p != NULL) {
- BN_free(d->p);
- d->p = p;
- }
- if (q != NULL) {
- BN_free(d->q);
- d->q = q;
- }
- if (g != NULL) {
- BN_free(d->g);
- d->g = g;
- }
-
- return 1;
-}
-void DSA_get0_key(const DSA *d,
- const BIGNUM **pub_key, const BIGNUM **priv_key)
-{
- if (pub_key != NULL)
- *pub_key = d->pub_key;
- if (priv_key != NULL)
- *priv_key = d->priv_key;
-}
-int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
-{
- /* If the field pub_key in d is NULL, the corresponding input
- * parameters MUST be non-NULL. The priv_key field may
- * be left NULL.
- */
- if (d->pub_key == NULL && pub_key == NULL)
- return 0;
-
- if (pub_key != NULL) {
- BN_free(d->pub_key);
- d->pub_key = pub_key;
- }
- if (priv_key != NULL) {
- BN_free(d->priv_key);
- d->priv_key = priv_key;
- }
-
- return 1;
-}
-#endif
"""
diff --git a/src/_cffi_src/openssl/ec.py b/src/_cffi_src/openssl/ec.py
index 66bcadc23..6432fc22e 100644
--- a/src/_cffi_src/openssl/ec.py
+++ b/src/_cffi_src/openssl/ec.py
@@ -10,9 +10,7 @@ INCLUDES = """
"""
TYPES = """
-static const int Cryptography_HAS_EC;
static const int Cryptography_HAS_EC2M;
-static const int Cryptography_HAS_EC_1_0_2;
static const int OPENSSL_EC_NAMED_CURVE;
@@ -106,11 +104,11 @@ int EC_POINT_mul(const EC_GROUP *, EC_POINT *, const BIGNUM *,
int EC_METHOD_get_field_type(const EC_METHOD *);
const char *EC_curve_nid2nist(int);
+
+int EC_GROUP_get_asn1_flag(const EC_GROUP *);
"""
CUSTOMIZATIONS = """
-static const long Cryptography_HAS_EC = 1;
-
#if defined(OPENSSL_NO_EC2M)
static const long Cryptography_HAS_EC2M = 0;
@@ -125,11 +123,4 @@ int (*EC_POINT_set_compressed_coordinates_GF2m)(const EC_GROUP *, EC_POINT *,
#else
static const long Cryptography_HAS_EC2M = 1;
#endif
-
-#if (!CRYPTOGRAPHY_IS_LIBRESSL && CRYPTOGRAPHY_OPENSSL_LESS_THAN_102)
-static const long Cryptography_HAS_EC_1_0_2 = 0;
-const char *(*EC_curve_nid2nist)(int) = NULL;
-#else
-static const long Cryptography_HAS_EC_1_0_2 = 1;
-#endif
"""
diff --git a/src/_cffi_src/openssl/ecdh.py b/src/_cffi_src/openssl/ecdh.py
index 043635c41..c73cc9f36 100644
--- a/src/_cffi_src/openssl/ecdh.py
+++ b/src/_cffi_src/openssl/ecdh.py
@@ -9,8 +9,6 @@ INCLUDES = """
"""
TYPES = """
-static const int Cryptography_HAS_ECDH;
-static const int Cryptography_HAS_SET_ECDH_AUTO;
"""
FUNCTIONS = """
@@ -20,12 +18,4 @@ long SSL_CTX_set_ecdh_auto(SSL_CTX *, int);
"""
CUSTOMIZATIONS = """
-static const long Cryptography_HAS_ECDH = 1;
-
-#ifndef SSL_CTX_set_ecdh_auto
-static const long Cryptography_HAS_SET_ECDH_AUTO = 0;
-long (*SSL_CTX_set_ecdh_auto)(SSL_CTX *, int) = NULL;
-#else
-static const long Cryptography_HAS_SET_ECDH_AUTO = 1;
-#endif
"""
diff --git a/src/_cffi_src/openssl/ecdsa.py b/src/_cffi_src/openssl/ecdsa.py
index 44a778a68..3134e24b6 100644
--- a/src/_cffi_src/openssl/ecdsa.py
+++ b/src/_cffi_src/openssl/ecdsa.py
@@ -9,8 +9,6 @@ INCLUDES = """
"""
TYPES = """
-static const int Cryptography_HAS_ECDSA;
-
typedef ... ECDSA_SIG;
typedef ... CRYPTO_EX_new;
@@ -19,12 +17,6 @@ typedef ... CRYPTO_EX_free;
"""
FUNCTIONS = """
-ECDSA_SIG *ECDSA_SIG_new();
-void ECDSA_SIG_free(ECDSA_SIG *);
-int i2d_ECDSA_SIG(const ECDSA_SIG *, unsigned char **);
-ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **s, const unsigned char **, long);
-ECDSA_SIG *ECDSA_do_sign(const unsigned char *, int, EC_KEY *);
-int ECDSA_do_verify(const unsigned char *, int, const ECDSA_SIG *, EC_KEY *);
int ECDSA_sign(int, const unsigned char *, int, unsigned char *,
unsigned int *, EC_KEY *);
int ECDSA_verify(int, const unsigned char *, int, const unsigned char *, int,
@@ -34,5 +26,4 @@ int ECDSA_size(const EC_KEY *);
"""
CUSTOMIZATIONS = """
-static const long Cryptography_HAS_ECDSA = 1;
"""
diff --git a/src/_cffi_src/openssl/engine.py b/src/_cffi_src/openssl/engine.py
index 45ce95269..24cdd42a8 100644
--- a/src/_cffi_src/openssl/engine.py
+++ b/src/_cffi_src/openssl/engine.py
@@ -10,124 +10,56 @@ INCLUDES = """
TYPES = """
typedef ... ENGINE;
-typedef ... RSA_METHOD;
-typedef ... DSA_METHOD;
-typedef ... DH_METHOD;
-typedef struct {
- int (*bytes)(unsigned char *, int);
- int (*pseudorand)(unsigned char *, int);
- int (*status)();
- ...;
-} RAND_METHOD;
-typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *);
-typedef ... *ENGINE_CTRL_FUNC_PTR;
-typedef ... *ENGINE_LOAD_KEY_PTR;
-typedef ... *ENGINE_CIPHERS_PTR;
-typedef ... *ENGINE_DIGESTS_PTR;
-typedef ... ENGINE_CMD_DEFN;
typedef ... UI_METHOD;
-static const unsigned int ENGINE_METHOD_RSA;
-static const unsigned int ENGINE_METHOD_DSA;
-static const unsigned int ENGINE_METHOD_RAND;
-static const unsigned int ENGINE_METHOD_CIPHERS;
-static const unsigned int ENGINE_METHOD_DIGESTS;
-static const unsigned int ENGINE_METHOD_ALL;
-static const unsigned int ENGINE_METHOD_NONE;
-
-static const int ENGINE_R_CONFLICTING_ENGINE_ID;
+static const long Cryptography_HAS_ENGINE;
"""
FUNCTIONS = """
-ENGINE *ENGINE_get_first(void);
-ENGINE *ENGINE_get_last(void);
-ENGINE *ENGINE_get_next(ENGINE *);
-ENGINE *ENGINE_get_prev(ENGINE *);
-int ENGINE_add(ENGINE *);
-int ENGINE_remove(ENGINE *);
ENGINE *ENGINE_by_id(const char *);
int ENGINE_init(ENGINE *);
int ENGINE_finish(ENGINE *);
-void ENGINE_load_builtin_engines(void);
-ENGINE *ENGINE_get_default_RSA(void);
-ENGINE *ENGINE_get_default_DSA(void);
-ENGINE *ENGINE_get_default_DH(void);
ENGINE *ENGINE_get_default_RAND(void);
-ENGINE *ENGINE_get_cipher_engine(int);
-ENGINE *ENGINE_get_digest_engine(int);
-int ENGINE_set_default_RSA(ENGINE *);
-int ENGINE_set_default_DSA(ENGINE *);
-int ENGINE_set_default_DH(ENGINE *);
int ENGINE_set_default_RAND(ENGINE *);
-int ENGINE_set_default_ciphers(ENGINE *);
-int ENGINE_set_default_digests(ENGINE *);
-int ENGINE_set_default_string(ENGINE *, const char *);
-int ENGINE_set_default(ENGINE *, unsigned int);
-unsigned int ENGINE_get_table_flags(void);
-void ENGINE_set_table_flags(unsigned int);
-int ENGINE_register_RSA(ENGINE *);
-void ENGINE_unregister_RSA(ENGINE *);
-void ENGINE_register_all_RSA(void);
-int ENGINE_register_DSA(ENGINE *);
-void ENGINE_unregister_DSA(ENGINE *);
-void ENGINE_register_all_DSA(void);
-int ENGINE_register_DH(ENGINE *);
-void ENGINE_unregister_DH(ENGINE *);
-void ENGINE_register_all_DH(void);
-int ENGINE_register_RAND(ENGINE *);
void ENGINE_unregister_RAND(ENGINE *);
-void ENGINE_register_all_RAND(void);
-int ENGINE_register_ciphers(ENGINE *);
-void ENGINE_unregister_ciphers(ENGINE *);
-void ENGINE_register_all_ciphers(void);
-int ENGINE_register_digests(ENGINE *);
-void ENGINE_unregister_digests(ENGINE *);
-void ENGINE_register_all_digests(void);
-int ENGINE_register_complete(ENGINE *);
-int ENGINE_register_all_complete(void);
-int ENGINE_ctrl(ENGINE *, int, long, void *, void (*)(void));
-int ENGINE_cmd_is_executable(ENGINE *, int);
int ENGINE_ctrl_cmd(ENGINE *, const char *, long, void *, void (*)(void), int);
-int ENGINE_ctrl_cmd_string(ENGINE *, const char *, const char *, int);
-
-ENGINE *ENGINE_new(void);
int ENGINE_free(ENGINE *);
-int ENGINE_up_ref(ENGINE *);
-int ENGINE_set_id(ENGINE *, const char *);
-int ENGINE_set_name(ENGINE *, const char *);
-int ENGINE_set_RSA(ENGINE *, const RSA_METHOD *);
-int ENGINE_set_DSA(ENGINE *, const DSA_METHOD *);
-int ENGINE_set_DH(ENGINE *, const DH_METHOD *);
-int ENGINE_set_RAND(ENGINE *, const RAND_METHOD *);
-int ENGINE_set_destroy_function(ENGINE *, ENGINE_GEN_INT_FUNC_PTR);
-int ENGINE_set_init_function(ENGINE *, ENGINE_GEN_INT_FUNC_PTR);
-int ENGINE_set_finish_function(ENGINE *, ENGINE_GEN_INT_FUNC_PTR);
-int ENGINE_set_ctrl_function(ENGINE *, ENGINE_CTRL_FUNC_PTR);
-int ENGINE_set_load_privkey_function(ENGINE *, ENGINE_LOAD_KEY_PTR);
-int ENGINE_set_load_pubkey_function(ENGINE *, ENGINE_LOAD_KEY_PTR);
-int ENGINE_set_ciphers(ENGINE *, ENGINE_CIPHERS_PTR);
-int ENGINE_set_digests(ENGINE *, ENGINE_DIGESTS_PTR);
-int ENGINE_set_flags(ENGINE *, int);
-int ENGINE_set_cmd_defns(ENGINE *, const ENGINE_CMD_DEFN *);
-const char *ENGINE_get_id(const ENGINE *);
const char *ENGINE_get_name(const ENGINE *);
-const RSA_METHOD *ENGINE_get_RSA(const ENGINE *);
-const DSA_METHOD *ENGINE_get_DSA(const ENGINE *);
-const DH_METHOD *ENGINE_get_DH(const ENGINE *);
-const RAND_METHOD *ENGINE_get_RAND(const ENGINE *);
-const EVP_CIPHER *ENGINE_get_cipher(ENGINE *, int);
-const EVP_MD *ENGINE_get_digest(ENGINE *, int);
-int ENGINE_get_flags(const ENGINE *);
-const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *);
+// These bindings are unused by cryptography or pyOpenSSL but are present
+// for advanced users who need them.
+int ENGINE_ctrl_cmd_string(ENGINE *, const char *, const char *, int);
+void ENGINE_load_builtin_engines(void);
EVP_PKEY *ENGINE_load_private_key(ENGINE *, const char *, UI_METHOD *, void *);
EVP_PKEY *ENGINE_load_public_key(ENGINE *, const char *, UI_METHOD *, void *);
-void ENGINE_add_conf_module(void);
-/* these became macros in 1.1.0 */
-void ENGINE_load_openssl(void);
-void ENGINE_load_dynamic(void);
-void ENGINE_cleanup(void);
"""
CUSTOMIZATIONS = """
+#ifdef OPENSSL_NO_ENGINE
+static const long Cryptography_HAS_ENGINE = 0;
+
+ENGINE *(*ENGINE_by_id)(const char *) = NULL;
+int (*ENGINE_init)(ENGINE *) = NULL;
+int (*ENGINE_finish)(ENGINE *) = NULL;
+ENGINE *(*ENGINE_get_default_RAND)(void) = NULL;
+int (*ENGINE_set_default_RAND)(ENGINE *) = NULL;
+void (*ENGINE_unregister_RAND)(ENGINE *) = NULL;
+int (*ENGINE_ctrl_cmd)(ENGINE *, const char *, long, void *,
+ void (*)(void), int) = NULL;
+
+int (*ENGINE_free)(ENGINE *) = NULL;
+const char *(*ENGINE_get_id)(const ENGINE *) = NULL;
+const char *(*ENGINE_get_name)(const ENGINE *) = NULL;
+
+int (*ENGINE_ctrl_cmd_string)(ENGINE *, const char *, const char *,
+ int) = NULL;
+void (*ENGINE_load_builtin_engines)(void) = NULL;
+EVP_PKEY *(*ENGINE_load_private_key)(ENGINE *, const char *, UI_METHOD *,
+ void *) = NULL;
+EVP_PKEY *(*ENGINE_load_public_key)(ENGINE *, const char *,
+ UI_METHOD *, void *) = NULL;
+
+#else
+static const long Cryptography_HAS_ENGINE = 1;
+#endif
"""
diff --git a/src/_cffi_src/openssl/err.py b/src/_cffi_src/openssl/err.py
index d4033f5a4..0dd741467 100644
--- a/src/_cffi_src/openssl/err.py
+++ b/src/_cffi_src/openssl/err.py
@@ -9,141 +9,24 @@ INCLUDES = """
"""
TYPES = """
-static const int Cryptography_HAS_EC_CODES;
-static const int Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR;
-static const int Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED;
-
-static const int ERR_LIB_DH;
-static const int ERR_LIB_EVP;
-static const int ERR_LIB_EC;
-static const int ERR_LIB_PEM;
-static const int ERR_LIB_ASN1;
-static const int ERR_LIB_RSA;
-static const int ERR_LIB_PKCS12;
-static const int ERR_LIB_SSL;
-static const int ERR_LIB_X509;
-
-static const int ERR_R_MALLOC_FAILURE;
-static const int EVP_R_MEMORY_LIMIT_EXCEEDED;
-
-static const int ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
-static const int ASN1_R_BUFFER_TOO_SMALL;
-static const int ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER;
-static const int ASN1_R_DATA_IS_WRONG;
-static const int ASN1_R_DECODE_ERROR;
-static const int ASN1_R_DEPTH_EXCEEDED;
-static const int ASN1_R_ENCODE_ERROR;
-static const int ASN1_R_ERROR_GETTING_TIME;
-static const int ASN1_R_ERROR_LOADING_SECTION;
-static const int ASN1_R_MSTRING_WRONG_TAG;
-static const int ASN1_R_NESTED_ASN1_STRING;
-static const int ASN1_R_NO_MATCHING_CHOICE_TYPE;
-static const int ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM;
-static const int ASN1_R_UNKNOWN_OBJECT_TYPE;
-static const int ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE;
-static const int ASN1_R_UNKNOWN_TAG;
-static const int ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE;
-static const int ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE;
-static const int ASN1_R_UNSUPPORTED_TYPE;
-static const int ASN1_R_WRONG_TAG;
-static const int ASN1_R_NO_CONTENT_TYPE;
-static const int ASN1_R_NO_MULTIPART_BODY_FAILURE;
-static const int ASN1_R_NO_MULTIPART_BOUNDARY;
-static const int ASN1_R_HEADER_TOO_LONG;
-
-static const int DH_R_INVALID_PUBKEY;
-
static const int EVP_F_EVP_ENCRYPTFINAL_EX;
-
-static const int EVP_R_AES_KEY_SETUP_FAILED;
-static const int EVP_R_BAD_DECRYPT;
-static const int EVP_R_CIPHER_PARAMETER_ERROR;
-static const int EVP_R_CTRL_NOT_IMPLEMENTED;
-static const int EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED;
static const int EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH;
-static const int EVP_R_DECODE_ERROR;
-static const int EVP_R_DIFFERENT_KEY_TYPES;
-static const int EVP_R_INITIALIZATION_ERROR;
-static const int EVP_R_INPUT_NOT_INITIALIZED;
-static const int EVP_R_INVALID_KEY_LENGTH;
-static const int EVP_R_KEYGEN_FAILURE;
-static const int EVP_R_MISSING_PARAMETERS;
-static const int EVP_R_NO_CIPHER_SET;
-static const int EVP_R_NO_DIGEST_SET;
-static const int EVP_R_PUBLIC_KEY_NOT_RSA;
-static const int EVP_R_UNKNOWN_PBE_ALGORITHM;
-static const int EVP_R_UNSUPPORTED_CIPHER;
-static const int EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION;
-static const int EVP_R_UNSUPPORTED_KEYLENGTH;
-static const int EVP_R_UNSUPPORTED_SALT_TYPE;
+static const int EVP_R_BAD_DECRYPT;
static const int EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM;
-static const int EVP_R_WRONG_FINAL_BLOCK_LENGTH;
-static const int EVP_R_CAMELLIA_KEY_SETUP_FAILED;
-
-static const int EC_R_UNKNOWN_GROUP;
-
-static const int PEM_R_BAD_BASE64_DECODE;
-static const int PEM_R_BAD_DECRYPT;
-static const int PEM_R_BAD_END_LINE;
-static const int PEM_R_BAD_IV_CHARS;
-static const int PEM_R_BAD_PASSWORD_READ;
-static const int PEM_R_ERROR_CONVERTING_PRIVATE_KEY;
-static const int PEM_R_NO_START_LINE;
-static const int PEM_R_NOT_DEK_INFO;
-static const int PEM_R_NOT_ENCRYPTED;
-static const int PEM_R_NOT_PROC_TYPE;
-static const int PEM_R_PROBLEMS_GETTING_PASSWORD;
-static const int PEM_R_READ_KEY;
-static const int PEM_R_SHORT_HEADER;
-static const int PEM_R_UNSUPPORTED_CIPHER;
-static const int PEM_R_UNSUPPORTED_ENCRYPTION;
-
static const int PKCS12_R_PKCS12_CIPHERFINAL_ERROR;
+static const int PEM_R_UNSUPPORTED_ENCRYPTION;
+static const int EVP_R_UNKNOWN_PBE_ALGORITHM;
-static const int RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE;
-static const int RSA_R_DATA_TOO_LARGE_FOR_MODULUS;
-static const int RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY;
-static const int RSA_R_BLOCK_TYPE_IS_NOT_01;
-static const int RSA_R_BLOCK_TYPE_IS_NOT_02;
-static const int RSA_R_PKCS_DECODING_ERROR;
-static const int RSA_R_OAEP_DECODING_ERROR;
+static const int ERR_LIB_EVP;
+static const int ERR_LIB_PEM;
+static const int ERR_LIB_ASN1;
+static const int ERR_LIB_PKCS12;
static const int SSL_TLSEXT_ERR_OK;
-static const int SSL_TLSEXT_ERR_ALERT_WARNING;
static const int SSL_TLSEXT_ERR_ALERT_FATAL;
static const int SSL_TLSEXT_ERR_NOACK;
-static const int SSL_AD_CLOSE_NOTIFY;
-static const int SSL_AD_UNEXPECTED_MESSAGE;
-static const int SSL_AD_BAD_RECORD_MAC;
-static const int SSL_AD_RECORD_OVERFLOW;
-static const int SSL_AD_DECOMPRESSION_FAILURE;
-static const int SSL_AD_HANDSHAKE_FAILURE;
-static const int SSL_AD_BAD_CERTIFICATE;
-static const int SSL_AD_UNSUPPORTED_CERTIFICATE;
-static const int SSL_AD_CERTIFICATE_REVOKED;
-static const int SSL_AD_CERTIFICATE_EXPIRED;
-static const int SSL_AD_CERTIFICATE_UNKNOWN;
-static const int SSL_AD_ILLEGAL_PARAMETER;
-static const int SSL_AD_UNKNOWN_CA;
-static const int SSL_AD_ACCESS_DENIED;
-static const int SSL_AD_DECODE_ERROR;
-static const int SSL_AD_DECRYPT_ERROR;
-static const int SSL_AD_PROTOCOL_VERSION;
-static const int SSL_AD_INSUFFICIENT_SECURITY;
-static const int SSL_AD_INTERNAL_ERROR;
-static const int SSL_AD_USER_CANCELLED;
-static const int SSL_AD_NO_RENEGOTIATION;
-
-static const int SSL_AD_UNSUPPORTED_EXTENSION;
-static const int SSL_AD_CERTIFICATE_UNOBTAINABLE;
-static const int SSL_AD_UNRECOGNIZED_NAME;
-static const int SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
-static const int SSL_AD_BAD_CERTIFICATE_HASH_VALUE;
-static const int SSL_AD_UNKNOWN_PSK_IDENTITY;
-
static const int X509_R_CERT_ALREADY_IN_HASH_TABLE;
-static const int X509_R_KEY_VALUES_MISMATCH;
"""
FUNCTIONS = """
@@ -153,7 +36,6 @@ const char *ERR_func_error_string(unsigned long);
const char *ERR_reason_error_string(unsigned long);
unsigned long ERR_get_error(void);
unsigned long ERR_peek_error(void);
-unsigned long ERR_peek_last_error(void);
void ERR_clear_error(void);
void ERR_put_error(int, int, int, const char *, int);
@@ -164,19 +46,4 @@ int ERR_GET_REASON(unsigned long);
"""
CUSTOMIZATIONS = """
-static const long Cryptography_HAS_EC_CODES = 1;
-
-#ifdef RSA_R_PKCS_DECODING_ERROR
-static const long Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR = 1;
-#else
-static const long Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR = 0;
-static const long RSA_R_PKCS_DECODING_ERROR = 0;
-#endif
-
-#ifdef EVP_R_MEMORY_LIMIT_EXCEEDED
-static const long Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED = 1;
-#else
-static const long EVP_R_MEMORY_LIMIT_EXCEEDED = 0;
-static const long Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED = 0;
-#endif
"""
diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py
index 9ae6025a4..ab7cfeb39 100644
--- a/src/_cffi_src/openssl/evp.py
+++ b/src/_cffi_src/openssl/evp.py
@@ -25,14 +25,12 @@ static const int EVP_PKEY_X25519;
static const int EVP_PKEY_ED25519;
static const int EVP_PKEY_X448;
static const int EVP_PKEY_ED448;
+static const int EVP_PKEY_POLY1305;
static const int EVP_MAX_MD_SIZE;
static const int EVP_CTRL_AEAD_SET_IVLEN;
static const int EVP_CTRL_AEAD_GET_TAG;
static const int EVP_CTRL_AEAD_SET_TAG;
-static const int Cryptography_HAS_GCM;
-static const int Cryptography_HAS_PBKDF2_HMAC;
-static const int Cryptography_HAS_PKEY_CTX;
static const int Cryptography_HAS_SCRYPT;
static const int Cryptography_HAS_EVP_PKEY_DHX;
static const int Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint;
@@ -43,23 +41,12 @@ static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF;
FUNCTIONS = """
const EVP_CIPHER *EVP_get_cipherbyname(const char *);
-int EVP_EncryptInit_ex(EVP_CIPHER_CTX *, const EVP_CIPHER *, ENGINE *,
- const unsigned char *, const unsigned char *);
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *, int);
-int EVP_EncryptUpdate(EVP_CIPHER_CTX *, unsigned char *, int *,
- const unsigned char *, int);
-int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *);
-int EVP_DecryptInit_ex(EVP_CIPHER_CTX *, const EVP_CIPHER *, ENGINE *,
- const unsigned char *, const unsigned char *);
-int EVP_DecryptUpdate(EVP_CIPHER_CTX *, unsigned char *, int *,
- const unsigned char *, int);
-int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *);
int EVP_CipherInit_ex(EVP_CIPHER_CTX *, const EVP_CIPHER *, ENGINE *,
const unsigned char *, const unsigned char *, int);
int EVP_CipherUpdate(EVP_CIPHER_CTX *, unsigned char *, int *,
const unsigned char *, int);
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *);
-int EVP_CIPHER_block_size(const EVP_CIPHER *);
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *);
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *);
@@ -72,8 +59,6 @@ int EVP_DigestUpdate(EVP_MD_CTX *, const void *, size_t);
int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *);
int EVP_DigestFinalXOF(EVP_MD_CTX *, unsigned char *, size_t);
const EVP_MD *EVP_get_digestbyname(const char *);
-const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *);
-int EVP_MD_size(const EVP_MD *);
EVP_PKEY *EVP_PKEY_new(void);
void EVP_PKEY_free(EVP_PKEY *);
@@ -97,22 +82,14 @@ int EVP_VerifyUpdate(EVP_MD_CTX *, const void *, size_t);
int EVP_VerifyFinal(EVP_MD_CTX *, const unsigned char *, unsigned int,
EVP_PKEY *);
-const EVP_MD *EVP_md5(void);
-const EVP_MD *EVP_sha1(void);
-const EVP_MD *EVP_ripemd160(void);
-const EVP_MD *EVP_sha224(void);
-const EVP_MD *EVP_sha256(void);
-const EVP_MD *EVP_sha384(void);
-const EVP_MD *EVP_sha512(void);
-
int EVP_DigestSignInit(EVP_MD_CTX *, EVP_PKEY_CTX **, const EVP_MD *,
ENGINE *, EVP_PKEY *);
+int EVP_DigestSignUpdate(EVP_MD_CTX *, const void *, size_t);
+int EVP_DigestSignFinal(EVP_MD_CTX *, unsigned char *, size_t *);
int EVP_DigestVerifyInit(EVP_MD_CTX *, EVP_PKEY_CTX **, const EVP_MD *,
ENGINE *, EVP_PKEY *);
-int PKCS5_PBKDF2_HMAC_SHA1(const char *, int, const unsigned char *, int, int,
- int, unsigned char *);
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *, ENGINE *);
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int, ENGINE *);
@@ -124,6 +101,9 @@ int EVP_PKEY_sign(EVP_PKEY_CTX *, unsigned char *, size_t *,
int EVP_PKEY_verify_init(EVP_PKEY_CTX *);
int EVP_PKEY_verify(EVP_PKEY_CTX *, const unsigned char *, size_t,
const unsigned char *, size_t);
+int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *);
+int EVP_PKEY_verify_recover(EVP_PKEY_CTX *, unsigned char *,
+ size_t *, const unsigned char *, size_t);
int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *);
int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *);
@@ -131,18 +111,6 @@ int EVP_PKEY_set1_RSA(EVP_PKEY *, RSA *);
int EVP_PKEY_set1_DSA(EVP_PKEY *, DSA *);
int EVP_PKEY_set1_DH(EVP_PKEY *, DH *);
-int EVP_PKEY_get_attr_count(const EVP_PKEY *);
-int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *, int, int);
-X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *, int);
-X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *, int);
-int EVP_PKEY_add1_attr(EVP_PKEY *, X509_ATTRIBUTE *);
-int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *, const ASN1_OBJECT *, int,
- const unsigned char *, int);
-int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *, int, int,
- const unsigned char *, int);
-int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *, const char *, int,
- const unsigned char *, int);
-
int EVP_PKEY_cmp(const EVP_PKEY *, const EVP_PKEY *);
int EVP_PKEY_keygen_init(EVP_PKEY_CTX *);
@@ -155,11 +123,12 @@ int EVP_PKEY_set_type(EVP_PKEY *, int);
int EVP_PKEY_id(const EVP_PKEY *);
int Cryptography_EVP_PKEY_id(const EVP_PKEY *);
-/* in 1.1.0 _create and _destroy were renamed to _new and _free. The following
- two functions wrap both the old and new functions so we can call them
- without worrying about what OpenSSL we're running against. */
+EVP_MD_CTX *EVP_MD_CTX_new(void);
+void EVP_MD_CTX_free(EVP_MD_CTX *);
+/* Backwards compat aliases for pyOpenSSL */
EVP_MD_CTX *Cryptography_EVP_MD_CTX_new(void);
void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *);
+
/* Added in 1.1.1 */
int EVP_DigestSign(EVP_MD_CTX *, unsigned char *, size_t *,
const unsigned char *, size_t);
@@ -170,25 +139,15 @@ size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *, unsigned char **);
int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *, const unsigned char *,
size_t);
-/* PKCS8_PRIV_KEY_INFO * became const in 1.1.0 */
-EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *);
-
/* EVP_PKEY * became const in 1.1.0 */
int EVP_PKEY_bits(EVP_PKEY *);
-/* became a macro in 1.1.0 */
-void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *);
-
void OpenSSL_add_all_algorithms(void);
int EVP_PKEY_assign_RSA(EVP_PKEY *, RSA *);
-int EVP_PKEY_assign_DSA(EVP_PKEY *, DSA *);
-int EVP_PKEY_assign_EC_KEY(EVP_PKEY *, EC_KEY *);
EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *);
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *, EC_KEY *);
-int EVP_MD_CTX_block_size(const EVP_MD_CTX *);
-int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *);
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *, int, int, void *);
int PKCS5_PBKDF2_HMAC(const char *, int, const unsigned char *, int, int,
@@ -209,11 +168,6 @@ int EVP_PKEY_get_raw_public_key(const EVP_PKEY *, unsigned char *, size_t *);
"""
CUSTOMIZATIONS = """
-const long Cryptography_HAS_GCM = 1;
-
-const long Cryptography_HAS_PBKDF2_HMAC = 1;
-const long Cryptography_HAS_PKEY_CTX = 1;
-
#ifdef EVP_PKEY_DHX
const long Cryptography_HAS_EVP_PKEY_DHX = 1;
#else
@@ -224,22 +178,14 @@ const long EVP_PKEY_DHX = -1;
int Cryptography_EVP_PKEY_id(const EVP_PKEY *key) {
return EVP_PKEY_id(key);
}
-
EVP_MD_CTX *Cryptography_EVP_MD_CTX_new(void) {
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
- return EVP_MD_CTX_create();
-#else
return EVP_MD_CTX_new();
-#endif
}
-void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *ctx) {
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
- EVP_MD_CTX_destroy(ctx);
-#else
- EVP_MD_CTX_free(ctx);
-#endif
+void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *md) {
+ EVP_MD_CTX_free(md);
}
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 || defined(OPENSSL_NO_SCRYPT)
+
+#if CRYPTOGRAPHY_IS_LIBRESSL || defined(OPENSSL_NO_SCRYPT)
static const long Cryptography_HAS_SCRYPT = 0;
int (*EVP_PBE_scrypt)(const char *, size_t, const unsigned char *, size_t,
uint64_t, uint64_t, uint64_t, uint64_t, unsigned char *,
@@ -248,7 +194,7 @@ int (*EVP_PBE_scrypt)(const char *, size_t, const unsigned char *, size_t,
static const long Cryptography_HAS_SCRYPT = 1;
#endif
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+#if !CRYPTOGRAPHY_IS_LIBRESSL
static const long Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint = 1;
#else
static const long Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint = 0;
@@ -317,4 +263,10 @@ static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF = 1;
#ifndef EVP_PKEY_ED448
#define EVP_PKEY_ED448 NID_ED448
#endif
+
+/* This is tied to poly1305 support so we reuse the Cryptography_HAS_POLY1305
+ conditional to remove it. */
+#ifndef EVP_PKEY_POLY1305
+#define EVP_PKEY_POLY1305 NID_poly1305
+#endif
"""
diff --git a/src/_cffi_src/openssl/hmac.py b/src/_cffi_src/openssl/hmac.py
index b006e642d..2e0e33ffe 100644
--- a/src/_cffi_src/openssl/hmac.py
+++ b/src/_cffi_src/openssl/hmac.py
@@ -18,31 +18,9 @@ int HMAC_Update(HMAC_CTX *, const unsigned char *, size_t);
int HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *);
int HMAC_CTX_copy(HMAC_CTX *, HMAC_CTX *);
-HMAC_CTX *Cryptography_HMAC_CTX_new(void);
-void Cryptography_HMAC_CTX_free(HMAC_CTX *ctx);
+HMAC_CTX *HMAC_CTX_new(void);
+void HMAC_CTX_free(HMAC_CTX *ctx);
"""
CUSTOMIZATIONS = """
-HMAC_CTX *Cryptography_HMAC_CTX_new(void) {
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
- return HMAC_CTX_new();
-#else
- /* This uses OPENSSL_zalloc in 1.1.0, which is malloc + memset */
- HMAC_CTX *ctx = (HMAC_CTX *)OPENSSL_malloc(sizeof(HMAC_CTX));
- memset(ctx, 0, sizeof(HMAC_CTX));
- return ctx;
-#endif
-}
-
-
-void Cryptography_HMAC_CTX_free(HMAC_CTX *ctx) {
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
- return HMAC_CTX_free(ctx);
-#else
- if (ctx != NULL) {
- HMAC_CTX_cleanup(ctx);
- OPENSSL_free(ctx);
- }
-#endif
-}
"""
diff --git a/src/_cffi_src/openssl/nid.py b/src/_cffi_src/openssl/nid.py
index 4117b933a..9ef88cdbb 100644
--- a/src/_cffi_src/openssl/nid.py
+++ b/src/_cffi_src/openssl/nid.py
@@ -9,252 +9,44 @@ INCLUDES = """
"""
TYPES = """
-static const int Cryptography_HAS_X25519;
-static const int Cryptography_HAS_X448;
static const int Cryptography_HAS_ED448;
static const int Cryptography_HAS_ED25519;
+static const int Cryptography_HAS_POLY1305;
static const int NID_undef;
-static const int NID_dsa;
-static const int NID_dsaWithSHA;
-static const int NID_dsaWithSHA1;
-static const int NID_md2;
-static const int NID_md4;
-static const int NID_md5;
-static const int NID_mdc2;
-static const int NID_ripemd160;
-static const int NID_sha;
-static const int NID_sha1;
-static const int NID_sha256;
-static const int NID_sha384;
-static const int NID_sha512;
-static const int NID_sha224;
-static const int NID_sha;
-static const int NID_ecdsa_with_SHA1;
-static const int NID_ecdsa_with_SHA224;
-static const int NID_ecdsa_with_SHA256;
-static const int NID_ecdsa_with_SHA384;
-static const int NID_ecdsa_with_SHA512;
static const int NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
-static const int NID_X9_62_c2pnb163v1;
-static const int NID_X9_62_c2pnb163v2;
-static const int NID_X9_62_c2pnb163v3;
-static const int NID_X9_62_c2pnb176v1;
-static const int NID_X9_62_c2tnb191v1;
-static const int NID_X9_62_c2tnb191v2;
-static const int NID_X9_62_c2tnb191v3;
-static const int NID_X9_62_c2onb191v4;
-static const int NID_X9_62_c2onb191v5;
-static const int NID_X9_62_c2pnb208w1;
-static const int NID_X9_62_c2tnb239v1;
-static const int NID_X9_62_c2tnb239v2;
-static const int NID_X9_62_c2tnb239v3;
-static const int NID_X9_62_c2onb239v4;
-static const int NID_X9_62_c2onb239v5;
-static const int NID_X9_62_c2pnb272w1;
-static const int NID_X9_62_c2pnb304w1;
-static const int NID_X9_62_c2tnb359v1;
-static const int NID_X9_62_c2pnb368w1;
-static const int NID_X9_62_c2tnb431r1;
-static const int NID_X9_62_prime192v1;
-static const int NID_X9_62_prime192v2;
-static const int NID_X9_62_prime192v3;
-static const int NID_X9_62_prime239v1;
-static const int NID_X9_62_prime239v2;
-static const int NID_X9_62_prime239v3;
-static const int NID_X9_62_prime256v1;
-static const int NID_secp112r1;
-static const int NID_secp112r2;
-static const int NID_secp128r1;
-static const int NID_secp128r2;
-static const int NID_secp160k1;
-static const int NID_secp160r1;
-static const int NID_secp160r2;
-static const int NID_sect163k1;
-static const int NID_sect163r1;
-static const int NID_sect163r2;
-static const int NID_secp192k1;
-static const int NID_secp224k1;
-static const int NID_secp224r1;
-static const int NID_secp256k1;
-static const int NID_secp384r1;
-static const int NID_secp521r1;
-static const int NID_sect113r1;
-static const int NID_sect113r2;
-static const int NID_sect131r1;
-static const int NID_sect131r2;
-static const int NID_sect193r1;
-static const int NID_sect193r2;
-static const int NID_sect233k1;
-static const int NID_sect233r1;
-static const int NID_sect239k1;
-static const int NID_sect283k1;
-static const int NID_sect283r1;
-static const int NID_sect409k1;
-static const int NID_sect409r1;
-static const int NID_sect571k1;
-static const int NID_sect571r1;
static const int NID_X25519;
static const int NID_X448;
static const int NID_ED25519;
static const int NID_ED448;
-static const int NID_wap_wsg_idm_ecid_wtls1;
-static const int NID_wap_wsg_idm_ecid_wtls3;
-static const int NID_wap_wsg_idm_ecid_wtls4;
-static const int NID_wap_wsg_idm_ecid_wtls5;
-static const int NID_wap_wsg_idm_ecid_wtls6;
-static const int NID_wap_wsg_idm_ecid_wtls7;
-static const int NID_wap_wsg_idm_ecid_wtls8;
-static const int NID_wap_wsg_idm_ecid_wtls9;
-static const int NID_wap_wsg_idm_ecid_wtls10;
-static const int NID_wap_wsg_idm_ecid_wtls11;
-static const int NID_wap_wsg_idm_ecid_wtls12;
-static const int NID_ipsec3;
-static const int NID_ipsec4;
-static const char *const SN_X9_62_c2pnb163v1;
-static const char *const SN_X9_62_c2pnb163v2;
-static const char *const SN_X9_62_c2pnb163v3;
-static const char *const SN_X9_62_c2pnb176v1;
-static const char *const SN_X9_62_c2tnb191v1;
-static const char *const SN_X9_62_c2tnb191v2;
-static const char *const SN_X9_62_c2tnb191v3;
-static const char *const SN_X9_62_c2onb191v4;
-static const char *const SN_X9_62_c2onb191v5;
-static const char *const SN_X9_62_c2pnb208w1;
-static const char *const SN_X9_62_c2tnb239v1;
-static const char *const SN_X9_62_c2tnb239v2;
-static const char *const SN_X9_62_c2tnb239v3;
-static const char *const SN_X9_62_c2onb239v4;
-static const char *const SN_X9_62_c2onb239v5;
-static const char *const SN_X9_62_c2pnb272w1;
-static const char *const SN_X9_62_c2pnb304w1;
-static const char *const SN_X9_62_c2tnb359v1;
-static const char *const SN_X9_62_c2pnb368w1;
-static const char *const SN_X9_62_c2tnb431r1;
-static const char *const SN_X9_62_prime192v1;
-static const char *const SN_X9_62_prime192v2;
-static const char *const SN_X9_62_prime192v3;
-static const char *const SN_X9_62_prime239v1;
-static const char *const SN_X9_62_prime239v2;
-static const char *const SN_X9_62_prime239v3;
-static const char *const SN_X9_62_prime256v1;
-static const char *const SN_secp112r1;
-static const char *const SN_secp112r2;
-static const char *const SN_secp128r1;
-static const char *const SN_secp128r2;
-static const char *const SN_secp160k1;
-static const char *const SN_secp160r1;
-static const char *const SN_secp160r2;
-static const char *const SN_sect163k1;
-static const char *const SN_sect163r1;
-static const char *const SN_sect163r2;
-static const char *const SN_secp192k1;
-static const char *const SN_secp224k1;
-static const char *const SN_secp224r1;
-static const char *const SN_secp256k1;
-static const char *const SN_secp384r1;
-static const char *const SN_secp521r1;
-static const char *const SN_sect113r1;
-static const char *const SN_sect113r2;
-static const char *const SN_sect131r1;
-static const char *const SN_sect131r2;
-static const char *const SN_sect193r1;
-static const char *const SN_sect193r2;
-static const char *const SN_sect233k1;
-static const char *const SN_sect233r1;
-static const char *const SN_sect239k1;
-static const char *const SN_sect283k1;
-static const char *const SN_sect283r1;
-static const char *const SN_sect409k1;
-static const char *const SN_sect409r1;
-static const char *const SN_sect571k1;
-static const char *const SN_sect571r1;
-static const char *const SN_wap_wsg_idm_ecid_wtls1;
-static const char *const SN_wap_wsg_idm_ecid_wtls3;
-static const char *const SN_wap_wsg_idm_ecid_wtls4;
-static const char *const SN_wap_wsg_idm_ecid_wtls5;
-static const char *const SN_wap_wsg_idm_ecid_wtls6;
-static const char *const SN_wap_wsg_idm_ecid_wtls7;
-static const char *const SN_wap_wsg_idm_ecid_wtls8;
-static const char *const SN_wap_wsg_idm_ecid_wtls9;
-static const char *const SN_wap_wsg_idm_ecid_wtls10;
-static const char *const SN_wap_wsg_idm_ecid_wtls11;
-static const char *const SN_wap_wsg_idm_ecid_wtls12;
-static const char *const SN_ipsec3;
-static const char *const SN_ipsec4;
+static const int NID_poly1305;
-static const int NID_subject_key_identifier;
-static const int NID_authority_key_identifier;
-static const int NID_policy_constraints;
-static const int NID_ext_key_usage;
-static const int NID_info_access;
-static const int NID_key_usage;
static const int NID_subject_alt_name;
-static const int NID_issuer_alt_name;
-static const int NID_basic_constraints;
-static const int NID_issuing_distribution_point;
-static const int NID_certificate_issuer;
-static const int NID_name_constraints;
-static const int NID_crl_distribution_points;
-static const int NID_certificate_policies;
-static const int NID_inhibit_any_policy;
-
-static const int NID_private_key_usage_period;
-static const int NID_crl_number;
static const int NID_crl_reason;
-static const int NID_invalidity_date;
-static const int NID_delta_crl;
-static const int NID_any_policy;
-static const int NID_policy_mappings;
-static const int NID_target_information;
-static const int NID_no_rev_avail;
-
-static const int NID_commonName;
-static const int NID_countryName;
-static const int NID_localityName;
-static const int NID_stateOrProvinceName;
-static const int NID_organizationName;
-static const int NID_organizationalUnitName;
-static const int NID_serialNumber;
-static const int NID_surname;
-static const int NID_givenName;
-static const int NID_title;
-static const int NID_generationQualifier;
-static const int NID_dnQualifier;
-static const int NID_pseudonym;
-static const int NID_domainComponent;
-static const int NID_pkcs9_emailAddress;
-static const int NID_ad_OCSP;
-static const int NID_ad_ca_issuers;
+static const int NID_pkcs7_signed;
"""
FUNCTIONS = """
"""
CUSTOMIZATIONS = """
-#ifndef NID_X25519
-static const long Cryptography_HAS_X25519 = 0;
-static const int NID_X25519 = 0;
-#else
-static const long Cryptography_HAS_X25519 = 1;
-#endif
#ifndef NID_ED25519
static const long Cryptography_HAS_ED25519 = 0;
static const int NID_ED25519 = 0;
#else
static const long Cryptography_HAS_ED25519 = 1;
#endif
-#ifndef NID_X448
-static const long Cryptography_HAS_X448 = 0;
-static const int NID_X448 = 0;
-#else
-static const long Cryptography_HAS_X448 = 1;
-#endif
#ifndef NID_ED448
static const long Cryptography_HAS_ED448 = 0;
static const int NID_ED448 = 0;
#else
static const long Cryptography_HAS_ED448 = 1;
#endif
+#ifndef NID_poly1305
+static const long Cryptography_HAS_POLY1305 = 0;
+static const int NID_poly1305 = 0;
+#else
+static const long Cryptography_HAS_POLY1305 = 1;
+#endif
"""
diff --git a/src/_cffi_src/openssl/objects.py b/src/_cffi_src/openssl/objects.py
index 265ac75c0..236903d98 100644
--- a/src/_cffi_src/openssl/objects.py
+++ b/src/_cffi_src/openssl/objects.py
@@ -20,21 +20,13 @@ static const long OBJ_NAME_TYPE_MD_METH;
"""
FUNCTIONS = """
-ASN1_OBJECT *OBJ_nid2obj(int);
const char *OBJ_nid2ln(int);
const char *OBJ_nid2sn(int);
int OBJ_obj2nid(const ASN1_OBJECT *);
-int OBJ_ln2nid(const char *);
int OBJ_sn2nid(const char *);
int OBJ_txt2nid(const char *);
ASN1_OBJECT *OBJ_txt2obj(const char *, int);
int OBJ_obj2txt(char *, int, const ASN1_OBJECT *, int);
-int OBJ_cmp(const ASN1_OBJECT *, const ASN1_OBJECT *);
-ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *);
-int OBJ_create(const char *, const char *, const char *);
-void OBJ_NAME_do_all(int, void (*) (const OBJ_NAME *, void *), void *);
-/* OBJ_cleanup became a macro in 1.1.0 */
-void OBJ_cleanup(void);
"""
CUSTOMIZATIONS = """
diff --git a/src/_cffi_src/openssl/ocsp.py b/src/_cffi_src/openssl/ocsp.py
index 829314a32..c3d034c2c 100644
--- a/src/_cffi_src/openssl/ocsp.py
+++ b/src/_cffi_src/openssl/ocsp.py
@@ -46,8 +46,6 @@ int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *);
X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *, int);
int OCSP_request_onereq_count(OCSP_REQUEST *);
OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *, int);
-int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *);
-X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *, int);
OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *);
OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *, OCSP_CERTID *);
OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *, const X509 *, const X509 *);
@@ -59,7 +57,6 @@ void OCSP_BASICRESP_free(OCSP_BASICRESP *);
OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *, OCSP_CERTID *, int,
int, ASN1_TIME *, ASN1_TIME *,
ASN1_TIME *);
-int OCSP_basic_add1_nonce(OCSP_BASICRESP *, unsigned char *, int);
int OCSP_basic_add1_cert(OCSP_BASICRESP *, X509 *);
int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *, X509_EXTENSION *, int);
int OCSP_basic_sign(OCSP_BASICRESP *, X509 *, EVP_PKEY *, const EVP_MD *,
@@ -69,7 +66,6 @@ void OCSP_RESPONSE_free(OCSP_RESPONSE *);
OCSP_REQUEST *OCSP_REQUEST_new(void);
void OCSP_REQUEST_free(OCSP_REQUEST *);
-int OCSP_request_add1_nonce(OCSP_REQUEST *, unsigned char *, int);
int OCSP_REQUEST_add_ext(OCSP_REQUEST *, X509_EXTENSION *, int);
int OCSP_id_get0_info(ASN1_OCTET_STRING **, ASN1_OBJECT **,
ASN1_OCTET_STRING **, ASN1_INTEGER **, OCSP_CERTID *);
@@ -82,7 +78,7 @@ int i2d_OCSP_RESPDATA(OCSP_RESPDATA *, unsigned char **);
CUSTOMIZATIONS = """
#if ( \
- CRYPTOGRAPHY_OPENSSL_110_OR_GREATER && \
+ !CRYPTOGRAPHY_IS_LIBRESSL && \
CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J \
)
/* These structs come from ocsp_lcl.h and are needed to de-opaque the struct
@@ -109,7 +105,7 @@ struct ocsp_basic_response_st {
};
#endif
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
/* These functions are all taken from ocsp_cl.c in OpenSSL 1.1.0 */
const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single)
{
@@ -151,7 +147,7 @@ const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs)
#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J
const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs)
{
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
return bs->signatureAlgorithm;
#else
return &bs->signatureAlgorithm;
@@ -160,7 +156,7 @@ const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs)
const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs)
{
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
return bs->tbsResponseData;
#else
return &bs->tbsResponseData;
diff --git a/src/_cffi_src/openssl/pem.py b/src/_cffi_src/openssl/pem.py
index 55519bb1b..3f279c4ff 100644
--- a/src/_cffi_src/openssl/pem.py
+++ b/src/_cffi_src/openssl/pem.py
@@ -24,13 +24,9 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *, EVP_PKEY **, pem_password_cb *,
int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *,
char *, int, pem_password_cb *, void *);
-int PEM_write_bio_PKCS8PrivateKey_nid(BIO *, EVP_PKEY *, int, char *, int,
- pem_password_cb *, void *);
int i2d_PKCS8PrivateKey_bio(BIO *, EVP_PKEY *, const EVP_CIPHER *,
char *, int, pem_password_cb *, void *);
-int i2d_PKCS8PrivateKey_nid_bio(BIO *, EVP_PKEY *, int,
- char *, int, pem_password_cb *, void *);
int i2d_PKCS7_bio(BIO *, PKCS7 *);
PKCS7 *d2i_PKCS7_bio(BIO *, PKCS7 **);
@@ -46,17 +42,11 @@ X509_CRL *PEM_read_bio_X509_CRL(BIO *, X509_CRL **, pem_password_cb *, void *);
int PEM_write_bio_X509_CRL(BIO *, X509_CRL *);
-X509 *PEM_read_bio_X509_AUX(BIO *, X509 **, pem_password_cb *, void *);
-
PKCS7 *PEM_read_bio_PKCS7(BIO *, PKCS7 **, pem_password_cb *, void *);
int PEM_write_bio_PKCS7(BIO *, PKCS7 *);
DH *PEM_read_bio_DHparams(BIO *, DH **, pem_password_cb *, void *);
-DSA *PEM_read_bio_DSAPrivateKey(BIO *, DSA **, pem_password_cb *, void *);
-
-RSA *PEM_read_bio_RSAPrivateKey(BIO *, RSA **, pem_password_cb *, void *);
-
int PEM_write_bio_DSAPrivateKey(BIO *, DSA *, const EVP_CIPHER *,
unsigned char *, int,
pem_password_cb *, void *);
@@ -65,12 +55,8 @@ int PEM_write_bio_RSAPrivateKey(BIO *, RSA *, const EVP_CIPHER *,
unsigned char *, int,
pem_password_cb *, void *);
-DSA *PEM_read_bio_DSA_PUBKEY(BIO *, DSA **, pem_password_cb *, void *);
-
RSA *PEM_read_bio_RSAPublicKey(BIO *, RSA **, pem_password_cb *, void *);
-int PEM_write_bio_DSA_PUBKEY(BIO *, DSA *);
-
int PEM_write_bio_RSAPublicKey(BIO *, const RSA *);
EVP_PKEY *PEM_read_bio_PUBKEY(BIO *, EVP_PKEY **, pem_password_cb *, void *);
diff --git a/src/_cffi_src/openssl/pkcs7.py b/src/_cffi_src/openssl/pkcs7.py
index 1bece5b7e..c22263dfe 100644
--- a/src/_cffi_src/openssl/pkcs7.py
+++ b/src/_cffi_src/openssl/pkcs7.py
@@ -24,6 +24,7 @@ typedef struct {
typedef ... PKCS7_DIGEST;
typedef ... PKCS7_ENCRYPT;
typedef ... PKCS7_ENVELOPE;
+typedef ... PKCS7_SIGNER_INFO;
typedef struct {
ASN1_OBJECT *type;
@@ -51,33 +52,28 @@ static const int PKCS7_NOSMIMECAP;
static const int PKCS7_NOVERIFY;
static const int PKCS7_STREAM;
static const int PKCS7_TEXT;
+static const int PKCS7_PARTIAL;
"""
FUNCTIONS = """
-PKCS7 *SMIME_read_PKCS7(BIO *, BIO **);
-int SMIME_write_PKCS7(BIO *, PKCS7 *, BIO *, int);
-
void PKCS7_free(PKCS7 *);
-
PKCS7 *PKCS7_sign(X509 *, EVP_PKEY *, Cryptography_STACK_OF_X509 *,
- BIO *, int);
+ BIO *, int);
+int SMIME_write_PKCS7(BIO *, PKCS7 *, BIO *, int);
+int PEM_write_bio_PKCS7_stream(BIO *, PKCS7 *, BIO *, int);
+PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *, X509 *, EVP_PKEY *,
+ const EVP_MD *, int);
+int PKCS7_final(PKCS7 *, BIO *, int);
+/* Included verify due to external consumer, see
+ https://github.com/pyca/cryptography/issues/5433 */
int PKCS7_verify(PKCS7 *, Cryptography_STACK_OF_X509 *, X509_STORE *, BIO *,
BIO *, int);
-Cryptography_STACK_OF_X509 *PKCS7_get0_signers(PKCS7 *,
- Cryptography_STACK_OF_X509 *,
- int);
-
-PKCS7 *PKCS7_encrypt(Cryptography_STACK_OF_X509 *, BIO *,
- const EVP_CIPHER *, int);
-int PKCS7_decrypt(PKCS7 *, EVP_PKEY *, X509 *, BIO *, int);
+PKCS7 *SMIME_read_PKCS7(BIO *, BIO **);
-BIO *PKCS7_dataInit(PKCS7 *, BIO *);
-int PKCS7_type_is_encrypted(PKCS7 *);
int PKCS7_type_is_signed(PKCS7 *);
int PKCS7_type_is_enveloped(PKCS7 *);
int PKCS7_type_is_signedAndEnveloped(PKCS7 *);
int PKCS7_type_is_data(PKCS7 *);
-int PKCS7_type_is_digest(PKCS7 *);
"""
CUSTOMIZATIONS = ""
diff --git a/src/_cffi_src/openssl/rand.py b/src/_cffi_src/openssl/rand.py
index 686539279..1bc2ec0bc 100644
--- a/src/_cffi_src/openssl/rand.py
+++ b/src/_cffi_src/openssl/rand.py
@@ -9,10 +9,11 @@ INCLUDES = """
"""
TYPES = """
-static const long Cryptography_HAS_EGD;
+typedef ... RAND_METHOD;
"""
FUNCTIONS = """
+int RAND_set_rand_method(const RAND_METHOD *);
void RAND_add(const void *, int, double);
int RAND_status(void);
int RAND_bytes(unsigned char *, int);
@@ -21,11 +22,7 @@ int RAND_bytes(unsigned char *, int);
1 we'll just lie about the signature to preserve compatibility for
pyOpenSSL (which calls this in its rand.py as of mid-2016) */
void ERR_load_RAND_strings(void);
-
-/* RAND_cleanup became a macro in 1.1.0 */
-void RAND_cleanup(void);
"""
CUSTOMIZATIONS = """
-static const long Cryptography_HAS_EGD = 0;
"""
diff --git a/src/_cffi_src/openssl/rsa.py b/src/_cffi_src/openssl/rsa.py
index 216e633ab..92b8fa460 100644
--- a/src/_cffi_src/openssl/rsa.py
+++ b/src/_cffi_src/openssl/rsa.py
@@ -17,7 +17,6 @@ static const int RSA_PKCS1_OAEP_PADDING;
static const int RSA_PKCS1_PSS_PADDING;
static const int RSA_F4;
-static const int Cryptography_HAS_PSS_PADDING;
static const int Cryptography_HAS_RSA_OAEP_MD;
static const int Cryptography_HAS_RSA_OAEP_LABEL;
"""
@@ -25,19 +24,10 @@ static const int Cryptography_HAS_RSA_OAEP_LABEL;
FUNCTIONS = """
RSA *RSA_new(void);
void RSA_free(RSA *);
-int RSA_size(const RSA *);
int RSA_generate_key_ex(RSA *, int, BIGNUM *, BN_GENCB *);
int RSA_check_key(const RSA *);
RSA *RSAPublicKey_dup(RSA *);
int RSA_blinding_on(RSA *, BN_CTX *);
-int RSA_public_encrypt(int, const unsigned char *, unsigned char *,
- RSA *, int);
-int RSA_private_encrypt(int, const unsigned char *, unsigned char *,
- RSA *, int);
-int RSA_public_decrypt(int, const unsigned char *, unsigned char *,
- RSA *, int);
-int RSA_private_decrypt(int, const unsigned char *, unsigned char *,
- RSA *, int);
int RSA_print(BIO *, const RSA *, int);
/* added in 1.1.0 when the RSA struct was opaqued */
@@ -58,127 +48,14 @@ int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *, EVP_MD *);
"""
CUSTOMIZATIONS = """
-static const long Cryptography_HAS_PSS_PADDING = 1;
-
-#if defined(EVP_PKEY_CTX_set_rsa_oaep_md)
+#if !CRYPTOGRAPHY_IS_LIBRESSL
static const long Cryptography_HAS_RSA_OAEP_MD = 1;
-#else
-static const long Cryptography_HAS_RSA_OAEP_MD = 0;
-int (*EVP_PKEY_CTX_set_rsa_oaep_md)(EVP_PKEY_CTX *, EVP_MD *) = NULL;
-#endif
-
-#if defined(EVP_PKEY_CTX_set0_rsa_oaep_label)
static const long Cryptography_HAS_RSA_OAEP_LABEL = 1;
#else
+static const long Cryptography_HAS_RSA_OAEP_MD = 0;
static const long Cryptography_HAS_RSA_OAEP_LABEL = 0;
+int (*EVP_PKEY_CTX_set_rsa_oaep_md)(EVP_PKEY_CTX *, EVP_MD *) = NULL;
int (*EVP_PKEY_CTX_set0_rsa_oaep_label)(EVP_PKEY_CTX *, unsigned char *,
int) = NULL;
#endif
-
-/* These functions were added in OpenSSL 1.1.0 */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
-{
- /* If the fields n and e in r are NULL, the corresponding input
- * parameters MUST be non-NULL for n and e. d may be
- * left NULL (in case only the public key is used).
- */
- if ((r->n == NULL && n == NULL)
- || (r->e == NULL && e == NULL))
- return 0;
-
- if (n != NULL) {
- BN_free(r->n);
- r->n = n;
- }
- if (e != NULL) {
- BN_free(r->e);
- r->e = e;
- }
- if (d != NULL) {
- BN_free(r->d);
- r->d = d;
- }
-
- return 1;
-}
-
-int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
-{
- /* If the fields p and q in r are NULL, the corresponding input
- * parameters MUST be non-NULL.
- */
- if ((r->p == NULL && p == NULL)
- || (r->q == NULL && q == NULL))
- return 0;
-
- if (p != NULL) {
- BN_free(r->p);
- r->p = p;
- }
- if (q != NULL) {
- BN_free(r->q);
- r->q = q;
- }
-
- return 1;
-}
-
-int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
-{
- /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
- * parameters MUST be non-NULL.
- */
- if ((r->dmp1 == NULL && dmp1 == NULL)
- || (r->dmq1 == NULL && dmq1 == NULL)
- || (r->iqmp == NULL && iqmp == NULL))
- return 0;
-
- if (dmp1 != NULL) {
- BN_free(r->dmp1);
- r->dmp1 = dmp1;
- }
- if (dmq1 != NULL) {
- BN_free(r->dmq1);
- r->dmq1 = dmq1;
- }
- if (iqmp != NULL) {
- BN_free(r->iqmp);
- r->iqmp = iqmp;
- }
-
- return 1;
-}
-
-void RSA_get0_key(const RSA *r,
- const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
-{
- if (n != NULL)
- *n = r->n;
- if (e != NULL)
- *e = r->e;
- if (d != NULL)
- *d = r->d;
-}
-
-void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
-{
- if (p != NULL)
- *p = r->p;
- if (q != NULL)
- *q = r->q;
-}
-
-void RSA_get0_crt_params(const RSA *r,
- const BIGNUM **dmp1, const BIGNUM **dmq1,
- const BIGNUM **iqmp)
-{
- if (dmp1 != NULL)
- *dmp1 = r->dmp1;
- if (dmq1 != NULL)
- *dmq1 = r->dmq1;
- if (iqmp != NULL)
- *iqmp = r->iqmp;
-}
-#endif
"""
diff --git a/src/_cffi_src/openssl/src/osrandom_engine.c b/src/_cffi_src/openssl/src/osrandom_engine.c
index 697381c85..a84857b86 100644
--- a/src/_cffi_src/openssl/src/osrandom_engine.c
+++ b/src/_cffi_src/openssl/src/osrandom_engine.c
@@ -17,6 +17,9 @@
#include <poll.h>
#endif
+#if CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE
+/* OpenSSL has ENGINE support and is older than 1.1.1d (the first version that
+ * properly implements fork safety in its RNG) so build the engine. */
static const char *Cryptography_osrandom_engine_id = "osrandom";
/****************************************************************************
@@ -94,7 +97,18 @@ static struct {
ino_t st_ino;
} urandom_cache = { -1 };
-static int set_cloexec(int fd) {
+static int open_cloexec(const char *path) {
+ int open_flags = O_RDONLY;
+#ifdef O_CLOEXEC
+ open_flags |= O_CLOEXEC;
+#endif
+
+ int fd = open(path, open_flags);
+ if (fd == -1) {
+ return -1;
+ }
+
+#ifndef O_CLOEXEC
int flags = fcntl(fd, F_GETFD);
if (flags == -1) {
return -1;
@@ -102,7 +116,8 @@ static int set_cloexec(int fd) {
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
return -1;
}
- return 0;
+#endif
+ return fd;
}
#ifdef __linux__
@@ -114,13 +129,10 @@ static int set_cloexec(int fd) {
static int wait_on_devrandom(void) {
struct pollfd pfd = {};
int ret = 0;
- int random_fd = open("/dev/random", O_RDONLY);
+ int random_fd = open_cloexec("/dev/random");
if (random_fd < 0) {
return -1;
}
- if (set_cloexec(random_fd) < 0) {
- return -1;
- }
pfd.fd = random_fd;
pfd.events = POLLIN;
pfd.revents = 0;
@@ -154,13 +166,10 @@ static int dev_urandom_fd(void) {
}
#endif
- fd = open("/dev/urandom", O_RDONLY);
+ fd = open_cloexec("/dev/urandom");
if (fd < 0) {
goto error;
}
- if (set_cloexec(fd) < 0) {
- goto error;
- }
if (fstat(fd, &st)) {
goto error;
}
@@ -243,7 +252,7 @@ static int osrandom_init(ENGINE *e) {
#if !defined(__APPLE__)
getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS;
#else
- if (&getentropy != NULL) {
+ if (__builtin_available(macOS 10.12, *)) {
getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS;
} else {
getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK;
@@ -269,7 +278,11 @@ static int osrandom_rand_bytes(unsigned char *buffer, int size) {
while (size > 0) {
/* OpenBSD and macOS restrict maximum buffer size to 256. */
len = size > 256 ? 256 : size;
+/* on mac, availability is already checked using `__builtin_available` above */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability"
res = getentropy(buffer, (size_t)len);
+#pragma clang diagnostic pop
if (res < 0) {
ERR_Cryptography_OSRandom_error(
CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES,
@@ -516,7 +529,7 @@ static int osrandom_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_INVALID_ARGUMENT);
return 0;
}
- strncpy((char *)p, name, len);
+ strcpy((char *)p, name);
return (int)len;
default:
ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
@@ -632,3 +645,16 @@ int Cryptography_add_osrandom_engine(void) {
return 1;
}
+
+#else
+/* If OpenSSL has no ENGINE support then we don't want
+ * to compile the osrandom engine, but we do need some
+ * placeholders */
+static const char *Cryptography_osrandom_engine_id = "no-engine-support";
+static const char *Cryptography_osrandom_engine_name = "osrandom_engine disabled";
+
+int Cryptography_add_osrandom_engine(void) {
+ return 0;
+}
+
+#endif
diff --git a/src/_cffi_src/openssl/src/osrandom_engine.h b/src/_cffi_src/openssl/src/osrandom_engine.h
index 53f957fa6..93d918b88 100644
--- a/src/_cffi_src/openssl/src/osrandom_engine.h
+++ b/src/_cffi_src/openssl/src/osrandom_engine.h
@@ -1,10 +1,14 @@
+#ifndef OPENSSL_NO_ENGINE
+/* OpenSSL has ENGINE support so include all of this. */
#ifdef _WIN32
#include <Wincrypt.h>
#else
#include <fcntl.h>
#include <unistd.h>
/* for defined(BSD) */
- #include <sys/param.h>
+ #ifndef __MVS__
+ #include <sys/param.h>
+ #endif
#ifdef BSD
/* for SYS_getentropy */
@@ -24,6 +28,20 @@
#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x0001
#endif /* GRND_NONBLOCK */
+
+ #ifndef SYS_getrandom
+ /* We only bother to define the constants for platforms where we ship
+ * wheels, since that's the predominant way you get a situation where
+ * you don't have SYS_getrandom at compile time but do have the syscall
+ * at runtime */
+ #if defined(__x86_64__)
+ #define SYS_getrandom 318
+ #elif defined(__i386__)
+ #define SYS_getrandom 355
+ #elif defined(__aarch64__)
+ #define SYS_getrandom 278
+ #endif
+ #endif
#endif /* __linux__ */
#endif /* _WIN32 */
@@ -97,3 +115,4 @@ static void ERR_Cryptography_OSRandom_error(int function, int reason,
#define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED_UNEXPECTED 402
#define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_FAILED 403
#define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_NOT_INIT 404
+#endif
diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py
index 2218095cc..9400f115f 100644
--- a/src/_cffi_src/openssl/ssl.py
+++ b/src/_cffi_src/openssl/ssl.py
@@ -13,26 +13,18 @@ typedef STACK_OF(SSL_CIPHER) Cryptography_STACK_OF_SSL_CIPHER;
TYPES = """
static const long Cryptography_HAS_SSL_ST;
static const long Cryptography_HAS_TLS_ST;
-static const long Cryptography_HAS_SSL2;
static const long Cryptography_HAS_SSL3_METHOD;
static const long Cryptography_HAS_TLSv1_1;
static const long Cryptography_HAS_TLSv1_2;
static const long Cryptography_HAS_TLSv1_3;
static const long Cryptography_HAS_SECURE_RENEGOTIATION;
-static const long Cryptography_HAS_COMPRESSION;
-static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB;
-static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP;
-static const long Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE;
-static const long Cryptography_HAS_GET_SERVER_TMP_KEY;
-static const long Cryptography_HAS_SSL_CTX_SET_CLIENT_CERT_ENGINE;
static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS;
static const long Cryptography_HAS_DTLS;
-static const long Cryptography_HAS_GENERIC_DTLS_METHOD;
static const long Cryptography_HAS_SIGALGS;
static const long Cryptography_HAS_PSK;
-static const long Cryptography_HAS_CIPHER_DETAILS;
-
-/* Internally invented symbol to tell us if SNI is supported */
+static const long Cryptography_HAS_VERIFIED_CHAIN;
+static const long Cryptography_HAS_KEYLOG;
+static const long Cryptography_HAS_GET_PROTO_VERSION;
static const long Cryptography_HAS_TLSEXT_HOSTNAME;
/* Internally invented symbol to tell us if SSL_MODE_RELEASE_BUFFERS is
@@ -51,6 +43,7 @@ static const long Cryptography_HAS_ALPN;
static const long Cryptography_HAS_NEXTPROTONEG;
static const long Cryptography_HAS_SET_CERT_CB;
static const long Cryptography_HAS_CUSTOM_EXT;
+static const long Cryptography_HAS_SRTP;
static const long SSL_FILETYPE_PEM;
static const long SSL_FILETYPE_ASN1;
@@ -139,8 +132,6 @@ static const long SSL3_RANDOM_SIZE;
static const long TLS_ST_BEFORE;
static const long TLS_ST_OK;
-static const long OPENSSL_NPN_NEGOTIATED;
-
typedef ... SSL_METHOD;
typedef ... SSL_CTX;
@@ -153,7 +144,6 @@ static const long TLSEXT_STATUSTYPE_ocsp;
typedef ... SSL_CIPHER;
typedef ... Cryptography_STACK_OF_SSL_CIPHER;
-typedef ... COMP_METHOD;
typedef struct {
const char *name;
@@ -166,20 +156,10 @@ FUNCTIONS = """
const char *SSL_state_string_long(const SSL *);
SSL_SESSION *SSL_get1_session(SSL *);
int SSL_set_session(SSL *, SSL_SESSION *);
-int SSL_get_verify_mode(const SSL *);
-void SSL_set_verify(SSL *, int, int (*)(int, X509_STORE_CTX *));
-void SSL_set_verify_depth(SSL *, int);
-int SSL_get_verify_depth(const SSL *);
-int (*SSL_get_verify_callback(const SSL *))(int, X509_STORE_CTX *);
-void SSL_set_info_callback(SSL *ssl, void (*)(const SSL *, int, int));
-void (*SSL_get_info_callback(const SSL *))(const SSL *, int, int);
SSL *SSL_new(SSL_CTX *);
void SSL_free(SSL *);
int SSL_set_fd(SSL *, int);
-SSL_CTX *SSL_get_SSL_CTX(const SSL *);
SSL_CTX *SSL_set_SSL_CTX(SSL *, SSL_CTX *);
-BIO *SSL_get_rbio(const SSL *);
-BIO *SSL_get_wbio(const SSL *);
void SSL_set_bio(SSL *, BIO *, BIO *);
void SSL_set_connect_state(SSL *);
void SSL_set_accept_state(SSL *);
@@ -195,28 +175,22 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void);
/* Added in 1.0.2 */
X509_VERIFY_PARAM *SSL_get0_param(SSL *);
-
-int SSL_use_certificate(SSL *, X509 *);
-int SSL_use_certificate_ASN1(SSL *, const unsigned char *, int);
-int SSL_use_certificate_file(SSL *, const char *, int);
-int SSL_use_PrivateKey(SSL *, EVP_PKEY *);
-int SSL_use_PrivateKey_ASN1(int, SSL *, const unsigned char *, long);
-int SSL_use_PrivateKey_file(SSL *, const char *, int);
-int SSL_check_private_key(const SSL *);
+X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *);
int SSL_get_sigalgs(SSL *, int, int *, int *, int *, unsigned char *,
unsigned char *);
Cryptography_STACK_OF_X509 *SSL_get_peer_cert_chain(const SSL *);
+Cryptography_STACK_OF_X509 *SSL_get0_verified_chain(const SSL *);
Cryptography_STACK_OF_X509_NAME *SSL_get_client_CA_list(const SSL *);
int SSL_get_error(const SSL *, int);
+long SSL_get_verify_result(const SSL *ssl);
int SSL_do_handshake(SSL *);
int SSL_shutdown(SSL *);
int SSL_renegotiate(SSL *);
int SSL_renegotiate_pending(SSL *);
const char *SSL_get_cipher_list(const SSL *, int);
-Cryptography_STACK_OF_SSL_CIPHER *SSL_get_ciphers(const SSL *);
/* context */
void SSL_CTX_free(SSL_CTX *);
@@ -224,7 +198,6 @@ long SSL_CTX_set_timeout(SSL_CTX *, long);
int SSL_CTX_set_default_verify_paths(SSL_CTX *);
void SSL_CTX_set_verify(SSL_CTX *, int, int (*)(int, X509_STORE_CTX *));
void SSL_CTX_set_verify_depth(SSL_CTX *, int);
-int (*SSL_CTX_get_verify_callback(const SSL_CTX *))(int, X509_STORE_CTX *);
int SSL_CTX_get_verify_mode(const SSL_CTX *);
int SSL_CTX_get_verify_depth(const SSL_CTX *);
int SSL_CTX_set_cipher_list(SSL_CTX *, const char *);
@@ -232,11 +205,9 @@ int SSL_CTX_load_verify_locations(SSL_CTX *, const char *, const char *);
void SSL_CTX_set_default_passwd_cb(SSL_CTX *, pem_password_cb *);
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *, void *);
int SSL_CTX_use_certificate(SSL_CTX *, X509 *);
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *, int, const unsigned char *);
int SSL_CTX_use_certificate_file(SSL_CTX *, const char *, int);
int SSL_CTX_use_certificate_chain_file(SSL_CTX *, const char *);
int SSL_CTX_use_PrivateKey(SSL_CTX *, EVP_PKEY *);
-int SSL_CTX_use_PrivateKey_ASN1(int, SSL_CTX *, const unsigned char *, long);
int SSL_CTX_use_PrivateKey_file(SSL_CTX *, const char *, int);
int SSL_CTX_check_private_key(const SSL_CTX *);
void SSL_CTX_set_cert_verify_callback(SSL_CTX *,
@@ -282,6 +253,10 @@ void SSL_CTX_set_client_CA_list(SSL_CTX *, Cryptography_STACK_OF_X509_NAME *);
void SSL_CTX_set_info_callback(SSL_CTX *, void (*)(const SSL *, int, int));
void (*SSL_CTX_get_info_callback(SSL_CTX *))(const SSL *, int, int);
+void SSL_CTX_set_keylog_callback(SSL_CTX *,
+ void (*)(const SSL *, const char *));
+void (*SSL_CTX_get_keylog_callback(SSL_CTX *))(const SSL *, const char *);
+
long SSL_CTX_set1_sigalgs_list(SSL_CTX *, const char *);
/* SSL_SESSION */
@@ -326,38 +301,36 @@ long SSL_SESSION_get_timeout(const SSL_SESSION *);
int SSL_SESSION_has_ticket(const SSL_SESSION *);
long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *);
-/* not a macro, but older OpenSSLs don't pass the args as const */
-char *SSL_CIPHER_description(const SSL_CIPHER *, char *, int);
-int SSL_SESSION_print(BIO *, const SSL_SESSION *);
-
-/* not macros, but will be conditionally bound so can't live in functions */
-const COMP_METHOD *SSL_get_current_compression(SSL *);
-const COMP_METHOD *SSL_get_current_expansion(SSL *);
-const char *SSL_COMP_get_name(const COMP_METHOD *);
-int SSL_CTX_set_client_cert_engine(SSL_CTX *, ENGINE *);
-
unsigned long SSL_set_mode(SSL *, unsigned long);
+unsigned long SSL_clear_mode(SSL *, unsigned long);
unsigned long SSL_get_mode(SSL *);
unsigned long SSL_set_options(SSL *, unsigned long);
unsigned long SSL_get_options(SSL *);
-void SSL_set_app_data(SSL *, char *);
-char * SSL_get_app_data(SSL *);
-void SSL_set_read_ahead(SSL *, int);
-
int SSL_want_read(const SSL *);
int SSL_want_write(const SSL *);
long SSL_total_renegotiations(SSL *);
long SSL_get_secure_renegotiation_support(SSL *);
+long SSL_CTX_set_min_proto_version(SSL_CTX *, int);
+long SSL_CTX_set_max_proto_version(SSL_CTX *, int);
+long SSL_set_min_proto_version(SSL *, int);
+long SSL_set_max_proto_version(SSL *, int);
+
+long SSL_CTX_get_min_proto_version(SSL_CTX *);
+long SSL_CTX_get_max_proto_version(SSL_CTX *);
+long SSL_get_min_proto_version(SSL *);
+long SSL_get_max_proto_version(SSL *);
+
/* Defined as unsigned long because SSL_OP_ALL is greater than signed 32-bit
and Windows defines long as 32-bit. */
unsigned long SSL_CTX_set_options(SSL_CTX *, unsigned long);
unsigned long SSL_CTX_clear_options(SSL_CTX *, unsigned long);
unsigned long SSL_CTX_get_options(SSL_CTX *);
unsigned long SSL_CTX_set_mode(SSL_CTX *, unsigned long);
+unsigned long SSL_CTX_clear_mode(SSL_CTX *, unsigned long);
unsigned long SSL_CTX_get_mode(SSL_CTX *);
unsigned long SSL_CTX_set_session_cache_mode(SSL_CTX *, unsigned long);
unsigned long SSL_CTX_get_session_cache_mode(SSL_CTX *);
@@ -369,10 +342,6 @@ unsigned long SSL_CTX_add_extra_chain_cert(SSL_CTX *, X509 *);
/* methods */
-/*
- * TLSv1_1 and TLSv1_2 are recent additions. Only sufficiently new versions of
- * OpenSSL support them.
- */
const SSL_METHOD *TLSv1_1_method(void);
const SSL_METHOD *TLSv1_1_server_method(void);
const SSL_METHOD *TLSv1_1_client_method(void);
@@ -402,6 +371,10 @@ const SSL_METHOD *SSLv23_method(void);
const SSL_METHOD *SSLv23_server_method(void);
const SSL_METHOD *SSLv23_client_method(void);
+const SSL_METHOD *TLS_method(void);
+const SSL_METHOD *TLS_server_method(void);
+const SSL_METHOD *TLS_client_method(void);
+
/*- These aren't macros these arguments are all const X on openssl > 1.0.x -*/
SSL_CTX *SSL_CTX_new(SSL_METHOD *);
long SSL_CTX_get_timeout(const SSL_CTX *);
@@ -432,25 +405,9 @@ SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *);
long SSL_session_reused(SSL *);
-void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *,
- int (*)(SSL *,
- const unsigned char **,
- unsigned int *,
- void *),
- void *);
-void SSL_CTX_set_next_proto_select_cb(SSL_CTX *,
- int (*)(SSL *,
- unsigned char **,
- unsigned char *,
- const unsigned char *,
- unsigned int,
- void *),
- void *);
int SSL_select_next_proto(unsigned char **, unsigned char *,
const unsigned char *, unsigned int,
const unsigned char *, unsigned int);
-void SSL_get0_next_proto_negotiated(const SSL *,
- const unsigned char **, unsigned *);
int sk_SSL_CIPHER_num(Cryptography_STACK_OF_SSL_CIPHER *);
const SSL_CIPHER *sk_SSL_CIPHER_value(Cryptography_STACK_OF_SSL_CIPHER *, int);
@@ -478,9 +435,6 @@ long SSL_get_server_tmp_key(SSL *, EVP_PKEY **);
void SSL_CTX_set_cert_cb(SSL_CTX *, int (*)(SSL *, void *), void *);
void SSL_set_cert_cb(SSL *, int (*)(SSL *, void *), void *);
-/* Added in 1.0.2 */
-const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *);
-
int SSL_SESSION_set1_id_context(SSL_SESSION *, const unsigned char *,
unsigned int);
/* Added in 1.1.0 for the great opaquing of structs */
@@ -551,75 +505,33 @@ int SSL_CTX_set_max_early_data(SSL_CTX *, uint32_t);
"""
CUSTOMIZATIONS = """
-/* Added in 1.0.2 but we need it in all versions now due to the great
- opaquing. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
-/* from ssl/ssl_lib.c */
-const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx) {
- return ctx->method;
-}
+// This symbol is being preserved because removing it will break users with
+// pyOpenSSL < 19.1 and pip < 20.x. We need to leave this in place until those
+// users have upgraded. PersistentlyDeprecated2020
+static const long Cryptography_HAS_TLSEXT_HOSTNAME = 1;
+
+#if CRYPTOGRAPHY_IS_LIBRESSL
+static const long Cryptography_HAS_VERIFIED_CHAIN = 0;
+Cryptography_STACK_OF_X509 *(*SSL_get0_verified_chain)(const SSL *) = NULL;
+#else
+static const long Cryptography_HAS_VERIFIED_CHAIN = 1;
#endif
-/* Added in 1.1.0 in the great opaquing, but we need to define it for older
- OpenSSLs. Such is our burden. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-/* from ssl/ssl_lib.c */
-size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen)
-{
- if (outlen == 0)
- return sizeof(ssl->s3->client_random);
- if (outlen > sizeof(ssl->s3->client_random))
- outlen = sizeof(ssl->s3->client_random);
- memcpy(out, ssl->s3->client_random, outlen);
- return outlen;
-}
-/* Added in 1.1.0 as well */
-/* from ssl/ssl_lib.c */
-size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen)
-{
- if (outlen == 0)
- return sizeof(ssl->s3->server_random);
- if (outlen > sizeof(ssl->s3->server_random))
- outlen = sizeof(ssl->s3->server_random);
- memcpy(out, ssl->s3->server_random, outlen);
- return outlen;
-}
-/* Added in 1.1.0 as well */
-/* from ssl/ssl_lib.c */
-size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
- unsigned char *out, size_t outlen)
-{
- if (session->master_key_length < 0) {
- /* Should never happen */
- return 0;
- }
- if (outlen == 0)
- return session->master_key_length;
- if (outlen > (size_t)session->master_key_length)
- outlen = session->master_key_length;
- memcpy(out, session->master_key, outlen);
- return outlen;
-}
-/* from ssl/ssl_sess.c */
-int SSL_SESSION_has_ticket(const SSL_SESSION *s)
-{
- return (s->tlsext_ticklen > 0) ? 1 : 0;
-}
-/* from ssl/ssl_sess.c */
-unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
-{
- return s->tlsext_tick_lifetime_hint;
-}
+#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111
+static const long Cryptography_HAS_KEYLOG = 0;
+void (*SSL_CTX_set_keylog_callback)(SSL_CTX *,
+ void (*) (const SSL *, const char *)
+ ) = NULL;
+void (*(*SSL_CTX_get_keylog_callback)(SSL_CTX *))(
+ const SSL *,
+ const char *
+ ) = NULL;
+#else
+static const long Cryptography_HAS_KEYLOG = 1;
#endif
static const long Cryptography_HAS_SECURE_RENEGOTIATION = 1;
-/* Cryptography now compiles out all SSLv2 bindings. This exists to allow
- * clients that use it to check for SSLv2 support to keep functioning as
- * expected.
- */
-static const long Cryptography_HAS_SSL2 = 0;
-
#ifdef OPENSSL_NO_SSL3_METHOD
static const long Cryptography_HAS_SSL3_METHOD = 0;
SSL_METHOD* (*SSLv3_method)(void) = NULL;
@@ -629,10 +541,6 @@ SSL_METHOD* (*SSLv3_server_method)(void) = NULL;
static const long Cryptography_HAS_SSL3_METHOD = 1;
#endif
-static const long Cryptography_HAS_TLSEXT_HOSTNAME = 1;
-static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB = 1;
-static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP = 1;
-static const long Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE = 1;
static const long Cryptography_HAS_RELEASE_BUFFERS = 1;
static const long Cryptography_HAS_OP_NO_COMPRESSION = 1;
static const long Cryptography_HAS_TLSv1_1 = 1;
@@ -640,38 +548,10 @@ static const long Cryptography_HAS_TLSv1_2 = 1;
static const long Cryptography_HAS_SSL_OP_MSIE_SSLV2_RSA_PADDING = 1;
static const long Cryptography_HAS_SSL_OP_NO_TICKET = 1;
static const long Cryptography_HAS_SSL_SET_SSL_CTX = 1;
-static const long Cryptography_HAS_NEXTPROTONEG = 1;
-
-/* SSL_get0_param was added in OpenSSL 1.0.2. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-X509_VERIFY_PARAM *(*SSL_get0_param)(SSL *) = NULL;
-#else
-#endif
-
-/* ALPN was added in OpenSSL 1.0.2. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 && !CRYPTOGRAPHY_IS_LIBRESSL
-int (*SSL_CTX_set_alpn_protos)(SSL_CTX *,
- const unsigned char *,
- unsigned) = NULL;
-int (*SSL_set_alpn_protos)(SSL *, const unsigned char *, unsigned) = NULL;
-void (*SSL_CTX_set_alpn_select_cb)(SSL_CTX *,
- int (*) (SSL *,
- const unsigned char **,
- unsigned char *,
- const unsigned char *,
- unsigned int,
- void *),
- void *) = NULL;
-void (*SSL_get0_alpn_selected)(const SSL *,
- const unsigned char **,
- unsigned *) = NULL;
-static const long Cryptography_HAS_ALPN = 0;
-#else
+static const long Cryptography_HAS_NEXTPROTONEG = 0;
static const long Cryptography_HAS_ALPN = 1;
-#endif
-/* SSL_CTX_set_cert_cb was added in OpenSSL 1.0.2. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
+#if CRYPTOGRAPHY_IS_LIBRESSL
void (*SSL_CTX_set_cert_cb)(SSL_CTX *, int (*)(SSL *, void *), void *) = NULL;
void (*SSL_set_cert_cb)(SSL *, int (*)(SSL *, void *), void *) = NULL;
static const long Cryptography_HAS_SET_CERT_CB = 0;
@@ -679,31 +559,11 @@ static const long Cryptography_HAS_SET_CERT_CB = 0;
static const long Cryptography_HAS_SET_CERT_CB = 1;
#endif
-
-/* In OpenSSL 1.0.2i+ the handling of COMP_METHOD when OPENSSL_NO_COMP was
- changed and we no longer need to typedef void */
-#if (defined(OPENSSL_NO_COMP) && CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I) || \
- CRYPTOGRAPHY_IS_LIBRESSL
-static const long Cryptography_HAS_COMPRESSION = 0;
-typedef void COMP_METHOD;
-#else
-static const long Cryptography_HAS_COMPRESSION = 1;
-#endif
-
-#if defined(SSL_CTRL_GET_SERVER_TMP_KEY)
-static const long Cryptography_HAS_GET_SERVER_TMP_KEY = 1;
-#else
-static const long Cryptography_HAS_GET_SERVER_TMP_KEY = 0;
-long (*SSL_get_server_tmp_key)(SSL *, EVP_PKEY **) = NULL;
-#endif
-
-static const long Cryptography_HAS_SSL_CTX_SET_CLIENT_CERT_ENGINE = 1;
-
static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS = 1;
/* in OpenSSL 1.1.0 the SSL_ST values were renamed to TLS_ST and several were
removed */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
static const long Cryptography_HAS_SSL_ST = 1;
#else
static const long Cryptography_HAS_SSL_ST = 0;
@@ -712,7 +572,7 @@ static const long SSL_ST_OK = 0;
static const long SSL_ST_INIT = 0;
static const long SSL_ST_RENEGOTIATE = 0;
#endif
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+#if !CRYPTOGRAPHY_IS_LIBRESSL
static const long Cryptography_HAS_TLS_ST = 1;
#else
static const long Cryptography_HAS_TLS_ST = 0;
@@ -720,17 +580,11 @@ static const long TLS_ST_BEFORE = 0;
static const long TLS_ST_OK = 0;
#endif
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
-static const long Cryptography_HAS_GENERIC_DTLS_METHOD = 0;
-const SSL_METHOD *(*DTLS_method)(void) = NULL;
-const SSL_METHOD *(*DTLS_server_method)(void) = NULL;
-const SSL_METHOD *(*DTLS_client_method)(void) = NULL;
+#if CRYPTOGRAPHY_IS_LIBRESSL
static const long SSL_OP_NO_DTLSv1 = 0;
static const long SSL_OP_NO_DTLSv1_2 = 0;
long (*DTLS_set_link_mtu)(SSL *, long) = NULL;
long (*DTLS_get_link_min_mtu)(SSL *) = NULL;
-#else
-static const long Cryptography_HAS_GENERIC_DTLS_METHOD = 1;
#endif
static const long Cryptography_HAS_DTLS = 1;
@@ -753,7 +607,7 @@ long Cryptography_DTLSv1_get_timeout(SSL *ssl, time_t *ptv_sec,
return r;
}
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
+#if CRYPTOGRAPHY_IS_LIBRESSL
static const long Cryptography_HAS_SIGALGS = 0;
const int (*SSL_get_sigalgs)(SSL *, int, int *, int *, int *, unsigned char *,
unsigned char *) = NULL;
@@ -785,53 +639,41 @@ void (*SSL_CTX_set_psk_client_callback)(SSL_CTX *,
static const long Cryptography_HAS_PSK = 1;
#endif
-/*
- * Custom extensions were added in 1.0.2. 1.1.1 is adding a more general
- * SSL_CTX_add_custom_ext function, but we're not binding that yet.
- */
-#if CRYPTOGRAPHY_OPENSSL_102_OR_GREATER
+#if !CRYPTOGRAPHY_IS_LIBRESSL
static const long Cryptography_HAS_CUSTOM_EXT = 1;
#else
static const long Cryptography_HAS_CUSTOM_EXT = 0;
-
typedef int (*custom_ext_add_cb)(SSL *, unsigned int,
const unsigned char **,
size_t *, int *,
void *);
-
typedef void (*custom_ext_free_cb)(SSL *, unsigned int,
const unsigned char *,
void *);
-
typedef int (*custom_ext_parse_cb)(SSL *, unsigned int,
const unsigned char *,
size_t, int *,
void *);
-
int (*SSL_CTX_add_client_custom_ext)(SSL_CTX *, unsigned int,
custom_ext_add_cb,
custom_ext_free_cb, void *,
custom_ext_parse_cb,
void *) = NULL;
-
int (*SSL_CTX_add_server_custom_ext)(SSL_CTX *, unsigned int,
custom_ext_add_cb,
custom_ext_free_cb, void *,
custom_ext_parse_cb,
void *) = NULL;
-
int (*SSL_extension_supported)(unsigned int) = NULL;
#endif
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int (*SSL_CIPHER_is_aead)(const SSL_CIPHER *) = NULL;
-int (*SSL_CIPHER_get_cipher_nid)(const SSL_CIPHER *) = NULL;
-int (*SSL_CIPHER_get_digest_nid)(const SSL_CIPHER *) = NULL;
-int (*SSL_CIPHER_get_kx_nid)(const SSL_CIPHER *) = NULL;
-int (*SSL_CIPHER_get_auth_nid)(const SSL_CIPHER *) = NULL;
-static const long Cryptography_HAS_CIPHER_DETAILS = 0;
+#ifndef OPENSSL_NO_SRTP
+static const long Cryptography_HAS_SRTP = 1;
#else
-static const long Cryptography_HAS_CIPHER_DETAILS = 1;
+static const long Cryptography_HAS_SRTP = 0;
+int (*SSL_CTX_set_tlsext_use_srtp)(SSL_CTX *, const char *) = NULL;
+int (*SSL_set_tlsext_use_srtp)(SSL *, const char *) = NULL;
+SRTP_PROTECTION_PROFILE * (*SSL_get_selected_srtp_profile)(SSL *) = NULL;
#endif
#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111
@@ -849,4 +691,15 @@ int (*SSL_CTX_set_max_early_data)(SSL_CTX *, uint32_t) = NULL;
#else
static const long Cryptography_HAS_TLSv1_3 = 1;
#endif
+
+#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 && !CRYPTOGRAPHY_IS_LIBRESSL
+static const long Cryptography_HAS_GET_PROTO_VERSION = 0;
+
+long (*SSL_CTX_get_min_proto_version)(SSL_CTX *) = NULL;
+long (*SSL_CTX_get_max_proto_version)(SSL_CTX *) = NULL;
+long (*SSL_get_min_proto_version)(SSL *) = NULL;
+long (*SSL_get_max_proto_version)(SSL *) = NULL;
+#else
+static const long Cryptography_HAS_GET_PROTO_VERSION = 1;
+#endif
"""
diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py
index 748c6c8c7..24946ea48 100644
--- a/src/_cffi_src/openssl/x509.py
+++ b/src/_cffi_src/openssl/x509.py
@@ -30,13 +30,10 @@ typedef struct {
} X509_ALGOR;
typedef ... X509_ATTRIBUTE;
-typedef ... X509_CINF;
typedef ... X509_EXTENSION;
typedef ... X509_EXTENSIONS;
typedef ... X509_REQ;
-typedef ... X509_REQ_INFO;
typedef ... X509_REVOKED;
-typedef ... X509_CRL_INFO;
typedef ... X509_CRL;
typedef ... X509;
@@ -44,39 +41,6 @@ typedef ... NETSCAPE_SPKI;
typedef ... PKCS8_PRIV_KEY_INFO;
-static const int X509_FLAG_COMPAT;
-static const int X509_FLAG_NO_HEADER;
-static const int X509_FLAG_NO_VERSION;
-static const int X509_FLAG_NO_SERIAL;
-static const int X509_FLAG_NO_SIGNAME;
-static const int X509_FLAG_NO_ISSUER;
-static const int X509_FLAG_NO_VALIDITY;
-static const int X509_FLAG_NO_SUBJECT;
-static const int X509_FLAG_NO_PUBKEY;
-static const int X509_FLAG_NO_EXTENSIONS;
-static const int X509_FLAG_NO_SIGDUMP;
-static const int X509_FLAG_NO_AUX;
-static const int X509_FLAG_NO_ATTRIBUTES;
-
-static const int XN_FLAG_SEP_MASK;
-static const int XN_FLAG_COMPAT;
-static const int XN_FLAG_SEP_COMMA_PLUS;
-static const int XN_FLAG_SEP_CPLUS_SPC;
-static const int XN_FLAG_SEP_SPLUS_SPC;
-static const int XN_FLAG_SEP_MULTILINE;
-static const int XN_FLAG_DN_REV;
-static const int XN_FLAG_FN_MASK;
-static const int XN_FLAG_FN_SN;
-static const int XN_FLAG_FN_LN;
-static const int XN_FLAG_FN_OID;
-static const int XN_FLAG_FN_NONE;
-static const int XN_FLAG_SPC_EQ;
-static const int XN_FLAG_DUMP_UNKNOWN_FIELDS;
-static const int XN_FLAG_FN_ALIGN;
-static const int XN_FLAG_RFC2253;
-static const int XN_FLAG_ONELINE;
-static const int XN_FLAG_MULTILINE;
-
typedef void (*sk_X509_EXTENSION_freefunc)(X509_EXTENSION *);
"""
@@ -108,14 +72,11 @@ int X509_set_subject_name(X509 *, X509_NAME *);
int X509_set_issuer_name(X509 *, X509_NAME *);
int X509_add_ext(X509 *, X509_EXTENSION *, int);
-X509_EXTENSION *X509_delete_ext(X509 *, int);
X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *);
ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *);
void X509_EXTENSION_free(X509_EXTENSION *);
-int i2d_X509(X509 *, unsigned char **);
-
int X509_REQ_set_version(X509_REQ *, long);
X509_REQ *X509_REQ_new(void);
void X509_REQ_free(X509_REQ *);
@@ -123,13 +84,17 @@ int X509_REQ_set_pubkey(X509_REQ *, EVP_PKEY *);
int X509_REQ_set_subject_name(X509_REQ *, X509_NAME *);
int X509_REQ_sign(X509_REQ *, EVP_PKEY *, const EVP_MD *);
int X509_REQ_verify(X509_REQ *, EVP_PKEY *);
-int X509_REQ_digest(const X509_REQ *, const EVP_MD *,
- unsigned char *, unsigned int *);
EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *);
-int X509_REQ_print(BIO *, X509_REQ *);
int X509_REQ_print_ex(BIO *, X509_REQ *, unsigned long, unsigned long);
int X509_REQ_add_extensions(X509_REQ *, X509_EXTENSIONS *);
X509_EXTENSIONS *X509_REQ_get_extensions(X509_REQ *);
+X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *, int);
+int X509_REQ_get_attr_by_OBJ(const X509_REQ *, const ASN1_OBJECT *, int);
+void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *, int, int, void *);
+ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *, int);
+int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *);
+int X509_REQ_add1_attr_by_OBJ(X509_REQ *, const ASN1_OBJECT *,
+ int, const unsigned char *, int);
int X509V3_EXT_print(BIO *, X509_EXTENSION *, unsigned long, int);
ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *);
@@ -186,40 +151,19 @@ int X509_set_serialNumber(X509 *, ASN1_INTEGER *);
const char *X509_verify_cert_error_string(long);
-const char *X509_get_default_cert_area(void);
const char *X509_get_default_cert_dir(void);
const char *X509_get_default_cert_file(void);
const char *X509_get_default_cert_dir_env(void);
const char *X509_get_default_cert_file_env(void);
-const char *X509_get_default_private_dir(void);
-
-int i2d_RSA_PUBKEY(RSA *, unsigned char **);
-RSA *d2i_RSA_PUBKEY(RSA **, const unsigned char **, long);
-RSA *d2i_RSAPublicKey(RSA **, const unsigned char **, long);
-RSA *d2i_RSAPrivateKey(RSA **, const unsigned char **, long);
-int i2d_DSA_PUBKEY(DSA *, unsigned char **);
-DSA *d2i_DSA_PUBKEY(DSA **, const unsigned char **, long);
-DSA *d2i_DSAPublicKey(DSA **, const unsigned char **, long);
-DSA *d2i_DSAPrivateKey(DSA **, const unsigned char **, long);
-
-RSA *d2i_RSAPrivateKey_bio(BIO *, RSA **);
+
int i2d_RSAPrivateKey_bio(BIO *, RSA *);
RSA *d2i_RSAPublicKey_bio(BIO *, RSA **);
int i2d_RSAPublicKey_bio(BIO *, RSA *);
-RSA *d2i_RSA_PUBKEY_bio(BIO *, RSA **);
-int i2d_RSA_PUBKEY_bio(BIO *, RSA *);
-DSA *d2i_DSA_PUBKEY_bio(BIO *, DSA **);
-int i2d_DSA_PUBKEY_bio(BIO *, DSA *);
-DSA *d2i_DSAPrivateKey_bio(BIO *, DSA **);
int i2d_DSAPrivateKey_bio(BIO *, DSA *);
-PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *,
- PKCS8_PRIV_KEY_INFO **);
-void PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *);
/* These became const X509 in 1.1.0 */
int X509_get_ext_count(X509 *);
X509_EXTENSION *X509_get_ext(X509 *, int);
-int X509_get_ext_by_NID(X509 *, int, int);
X509_NAME *X509_get_subject_name(X509 *);
X509_NAME *X509_get_issuer_name(X509 *);
@@ -242,18 +186,9 @@ int X509_CRL_get_ext_count(X509_CRL *);
int X509_CRL_get0_by_serial(X509_CRL *, X509_REVOKED **, ASN1_INTEGER *);
-/* these CRYPTO_EX_DATA functions became macros in 1.1.0 */
-int X509_get_ex_new_index(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *,
- CRYPTO_EX_free *);
-int X509_set_ex_data(X509 *, int, void *);
-void *X509_get_ex_data(X509 *, int);
-
+X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *);
X509_REVOKED *Cryptography_X509_REVOKED_dup(X509_REVOKED *);
-int i2d_X509_CINF(X509_CINF *, unsigned char **);
-int i2d_X509_CRL_INFO(X509_CRL_INFO *, unsigned char **);
-int i2d_X509_REQ_INFO(X509_REQ_INFO *, unsigned char **);
-
/* new in 1.0.2 */
int i2d_re_X509_tbs(X509 *, unsigned char **);
int X509_get_signature_nid(const X509 *);
@@ -267,6 +202,8 @@ long X509_get_version(X509 *);
ASN1_TIME *X509_get_notBefore(X509 *);
ASN1_TIME *X509_get_notAfter(X509 *);
+ASN1_TIME *X509_getm_notBefore(X509 *);
+ASN1_TIME *X509_getm_notAfter(X509 *);
long X509_REQ_get_version(X509_REQ *);
X509_NAME *X509_REQ_get_subject_name(X509_REQ *);
@@ -295,11 +232,6 @@ int sk_X509_CRL_num(Cryptography_STACK_OF_X509_CRL *);
int sk_X509_CRL_push(Cryptography_STACK_OF_X509_CRL *, X509_CRL *);
X509_CRL *sk_X509_CRL_value(Cryptography_STACK_OF_X509_CRL *, int);
-int i2d_RSAPublicKey(RSA *, unsigned char **);
-int i2d_RSAPrivateKey(RSA *, unsigned char **);
-int i2d_DSAPublicKey(DSA *, unsigned char **);
-int i2d_DSAPrivateKey(DSA *, unsigned char **);
-
long X509_CRL_get_version(X509_CRL *);
ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *);
ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *);
@@ -311,19 +243,14 @@ int X509_CRL_set_lastUpdate(X509_CRL *, ASN1_TIME *);
int X509_CRL_set_nextUpdate(X509_CRL *, ASN1_TIME *);
int X509_set_notBefore(X509 *, ASN1_TIME *);
int X509_set_notAfter(X509 *, ASN1_TIME *);
+int X509_set1_notBefore(X509 *, ASN1_TIME *);
+int X509_set1_notAfter(X509 *, ASN1_TIME *);
-int i2d_EC_PUBKEY(EC_KEY *, unsigned char **);
-EC_KEY *d2i_EC_PUBKEY(EC_KEY **, const unsigned char **, long);
EC_KEY *d2i_EC_PUBKEY_bio(BIO *, EC_KEY **);
int i2d_EC_PUBKEY_bio(BIO *, EC_KEY *);
-EC_KEY *d2i_ECPrivateKey(EC_KEY **, const unsigned char **, long);
EC_KEY *d2i_ECPrivateKey_bio(BIO *, EC_KEY **);
-int i2d_ECPrivateKey(EC_KEY *, unsigned char **);
int i2d_ECPrivateKey_bio(BIO *, EC_KEY *);
-EC_KEY *o2i_ECPublicKey(EC_KEY **, const unsigned char **, long);
-int i2o_ECPublicKey(EC_KEY *, unsigned char **);
-
// declared in safestack
int sk_ASN1_OBJECT_num(Cryptography_STACK_OF_ASN1_OBJECT *);
ASN1_OBJECT *sk_ASN1_OBJECT_value(Cryptography_STACK_OF_ASN1_OBJECT *, int);
@@ -343,30 +270,7 @@ void X509_REQ_get0_signature(const X509_REQ *, const ASN1_BIT_STRING **,
"""
CUSTOMIZATIONS = """
-/* Added in 1.0.2 beta but we need it in all versions now due to the great
- opaquing. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-/* from x509/x_x509.c version 1.0.2 */
-void X509_get0_signature(const ASN1_BIT_STRING **psig,
- const X509_ALGOR **palg, const X509 *x)
-{
- if (psig)
- *psig = x->signature;
- if (palg)
- *palg = x->sig_alg;
-}
-
-int X509_get_signature_nid(const X509 *x)
-{
- return OBJ_obj2nid(x->sig_alg->algorithm);
-}
-
-#endif
-
-/* Added in 1.0.2 but we need it in all versions now due to the great
- opaquing. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
-/* from x509/x_x509.c */
+#if CRYPTOGRAPHY_IS_LIBRESSL
int i2d_re_X509_tbs(X509 *x, unsigned char **pp)
{
/* in 1.0.2+ this function also sets x->cert_info->enc.modified = 1
@@ -378,20 +282,13 @@ int i2d_re_X509_tbs(X509 *x, unsigned char **pp)
}
#endif
-/* X509_REVOKED_dup only exists on 1.0.2+. It is implemented using
- IMPLEMENT_ASN1_DUP_FUNCTION. The below is the equivalent so we have
- it available on all OpenSSLs. */
+/* Being kept around for pyOpenSSL */
X509_REVOKED *Cryptography_X509_REVOKED_dup(X509_REVOKED *rev) {
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
- return ASN1_item_dup(ASN1_ITEM_rptr(X509_REVOKED), rev);
-#else
return X509_REVOKED_dup(rev);
-#endif
}
-
/* Added in 1.1.0 but we need it in all versions now due to the great
opaquing. */
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp)
{
req->req_info->enc.modified = 1;
@@ -401,42 +298,5 @@ int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **pp) {
crl->crl->enc.modified = 1;
return i2d_X509_CRL_INFO(crl->crl, pp);
}
-
-#if !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int X509_up_ref(X509 *x) {
- return CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
-}
-
-const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x)
-{
- return x->cert_info->signature;
-}
-
-/* from x509/x509_req.c */
-void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
- const X509_ALGOR **palg)
-{
- if (psig != NULL)
- *psig = req->signature;
- if (palg != NULL)
- *palg = req->sig_alg;
-}
-void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
- const X509_ALGOR **palg)
-{
- if (psig != NULL)
- *psig = crl->signature;
- if (palg != NULL)
- *palg = crl->sig_alg;
-}
-const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x)
-{
- return x->revocationDate;
-}
-const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x)
-{
- return x->serialNumber;
-}
-#endif
#endif
"""
diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py
index 42da3b1e1..ba3d3dbb1 100644
--- a/src/_cffi_src/openssl/x509_vfy.py
+++ b/src/_cffi_src/openssl/x509_vfy.py
@@ -19,11 +19,8 @@ typedef STACK_OF(X509_OBJECT) Cryptography_STACK_OF_X509_OBJECT;
"""
TYPES = """
-static const long Cryptography_HAS_102_VERIFICATION_ERROR_CODES;
-static const long Cryptography_HAS_102_VERIFICATION_PARAMS;
+static const long Cryptography_HAS_102_VERIFICATION;
static const long Cryptography_HAS_110_VERIFICATION_PARAMS;
-static const long Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST;
-static const long Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN;
static const long Cryptography_HAS_X509_STORE_CTX_GET_ISSUER;
typedef ... Cryptography_STACK_OF_ASN1_OBJECT;
@@ -222,67 +219,22 @@ void X509_STORE_set_get_issuer(X509_STORE *, X509_STORE_CTX_get_issuer_fn);
"""
CUSTOMIZATIONS = """
-/* OpenSSL 1.0.2+ verification parameters and error codes */
-#if CRYPTOGRAPHY_OPENSSL_102_OR_GREATER
-static const long Cryptography_HAS_102_VERIFICATION_ERROR_CODES = 1;
-static const long Cryptography_HAS_102_VERIFICATION_PARAMS = 1;
+#if !CRYPTOGRAPHY_IS_LIBRESSL
+static const long Cryptography_HAS_102_VERIFICATION = 1;
#else
-static const long Cryptography_HAS_102_VERIFICATION_ERROR_CODES = 0;
-static const long Cryptography_HAS_102_VERIFICATION_PARAMS = 0;
-
+static const long Cryptography_HAS_102_VERIFICATION = 0;
static const long X509_V_ERR_SUITE_B_INVALID_VERSION = 0;
static const long X509_V_ERR_SUITE_B_INVALID_ALGORITHM = 0;
static const long X509_V_ERR_SUITE_B_INVALID_CURVE = 0;
static const long X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM = 0;
static const long X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED = 0;
static const long X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 = 0;
-/* These 3 defines are unavailable in LibreSSL 2.5.x, but may be added
- in the future... */
-#ifndef X509_V_ERR_HOSTNAME_MISMATCH
-static const long X509_V_ERR_HOSTNAME_MISMATCH = 0;
-#endif
-#ifndef X509_V_ERR_EMAIL_MISMATCH
-static const long X509_V_ERR_EMAIL_MISMATCH = 0;
-#endif
-#ifndef X509_V_ERR_IP_ADDRESS_MISMATCH
-static const long X509_V_ERR_IP_ADDRESS_MISMATCH = 0;
-#endif
-#ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
-static const long X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT = 0;
-#endif
-#ifndef X509_CHECK_FLAG_NO_WILDCARDS
-static const long X509_CHECK_FLAG_NO_WILDCARDS = 0;
-#endif
-#ifndef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
-static const long X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS = 0;
-#endif
-#ifndef X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS
-static const long X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS = 0;
-#endif
-#ifndef X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS
-static const long X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS = 0;
-#endif
-
-/* X509_V_FLAG_TRUSTED_FIRST is also new in 1.0.2+, but it is added separately
- below because it shows up in some earlier 3rd party OpenSSL packages. */
static const long X509_V_FLAG_SUITEB_128_LOS_ONLY = 0;
static const long X509_V_FLAG_SUITEB_192_LOS = 0;
static const long X509_V_FLAG_SUITEB_128_LOS = 0;
-
-#if !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-int (*X509_VERIFY_PARAM_set1_host)(X509_VERIFY_PARAM *, const char *,
- size_t) = NULL;
-int (*X509_VERIFY_PARAM_set1_email)(X509_VERIFY_PARAM *, const char *,
- size_t) = NULL;
-int (*X509_VERIFY_PARAM_set1_ip)(X509_VERIFY_PARAM *, const unsigned char *,
- size_t) = NULL;
-int (*X509_VERIFY_PARAM_set1_ip_asc)(X509_VERIFY_PARAM *, const char *) = NULL;
-void (*X509_VERIFY_PARAM_set_hostflags)(X509_VERIFY_PARAM *,
- unsigned int) = NULL;
-#endif
#endif
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 || CRYPTOGRAPHY_IS_LIBRESSL
+#if CRYPTOGRAPHY_IS_LIBRESSL
static const long Cryptography_HAS_110_VERIFICATION_PARAMS = 0;
#ifndef X509_CHECK_FLAG_NEVER_CHECK_SUBJECT
static const long X509_CHECK_FLAG_NEVER_CHECK_SUBJECT = 0;
@@ -291,45 +243,7 @@ static const long X509_CHECK_FLAG_NEVER_CHECK_SUBJECT = 0;
static const long Cryptography_HAS_110_VERIFICATION_PARAMS = 1;
#endif
-/* OpenSSL 1.0.2+ or Solaris's backport */
-#ifdef X509_V_FLAG_PARTIAL_CHAIN
-static const long Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN = 1;
-#else
-static const long Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN = 0;
-static const long X509_V_FLAG_PARTIAL_CHAIN = 0;
-#endif
-
-/* OpenSSL 1.0.2+, *or* Fedora 20's flavor of OpenSSL 1.0.1e... */
-#ifdef X509_V_FLAG_TRUSTED_FIRST
-static const long Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST = 1;
-#else
-static const long Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST = 0;
-static const long X509_V_FLAG_TRUSTED_FIRST = 0;
-#endif
-
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_LIBRESSL_27_OR_GREATER
-Cryptography_STACK_OF_X509_OBJECT *X509_STORE_get0_objects(X509_STORE *ctx) {
- return ctx->objs;
-}
-X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *store) {
- return store->param;
-}
-int X509_OBJECT_get_type(const X509_OBJECT *x) {
- return x->type;
-}
-
-/* from x509/x509_vfy.c */
-X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx)
-{
- return ctx->cert;
-}
-
-X509 *X509_OBJECT_get0_X509(X509_OBJECT *x) {
- return x->data.x509;
-}
-#endif
-
-#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110
+#if CRYPTOGRAPHY_IS_LIBRESSL
static const long Cryptography_HAS_X509_STORE_CTX_GET_ISSUER = 0;
typedef void *X509_STORE_CTX_get_issuer_fn;
X509_STORE_CTX_get_issuer_fn (*X509_STORE_get_get_issuer)(X509_STORE *) = NULL;
diff --git a/src/_cffi_src/openssl/x509name.py b/src/_cffi_src/openssl/x509name.py
index f88c8b063..1fbe26aa7 100644
--- a/src/_cffi_src/openssl/x509name.py
+++ b/src/_cffi_src/openssl/x509name.py
@@ -35,7 +35,7 @@ void X509_NAME_ENTRY_free(X509_NAME_ENTRY *);
int X509_NAME_get_index_by_NID(X509_NAME *, int, int);
int X509_NAME_cmp(const X509_NAME *, const X509_NAME *);
X509_NAME *X509_NAME_dup(X509_NAME *);
-int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *);
+int X509_NAME_ENTRY_set(X509_NAME_ENTRY *);
/* These became const X509_NAME * in 1.1.0 */
int X509_NAME_entry_count(X509_NAME *);
X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *, int);
@@ -75,13 +75,4 @@ Cryptography_STACK_OF_X509_NAME_ENTRY *sk_X509_NAME_ENTRY_dup(
"""
CUSTOMIZATIONS = """
-#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
-int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *ne) {
- return X509_NAME_ENTRY_set(ne);
-}
-#else
-int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *ne) {
- return ne->set;
-}
-#endif
"""
diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py
index 193d2e233..596812065 100644
--- a/src/_cffi_src/openssl/x509v3.py
+++ b/src/_cffi_src/openssl/x509v3.py
@@ -177,6 +177,7 @@ typedef struct {
typedef void (*sk_GENERAL_NAME_freefunc)(GENERAL_NAME *);
typedef void (*sk_DIST_POINT_freefunc)(DIST_POINT *);
typedef void (*sk_POLICYINFO_freefunc)(POLICYINFO *);
+typedef void (*sk_ACCESS_DESCRIPTION_freefunc)(ACCESS_DESCRIPTION *);
"""
@@ -228,6 +229,8 @@ ACCESS_DESCRIPTION *sk_ACCESS_DESCRIPTION_value(
Cryptography_STACK_OF_ACCESS_DESCRIPTION *, int
);
void sk_ACCESS_DESCRIPTION_free(Cryptography_STACK_OF_ACCESS_DESCRIPTION *);
+void sk_ACCESS_DESCRIPTION_pop_free(Cryptography_STACK_OF_ACCESS_DESCRIPTION *,
+ sk_ACCESS_DESCRIPTION_freefunc);
int sk_ACCESS_DESCRIPTION_push(Cryptography_STACK_OF_ACCESS_DESCRIPTION *,
ACCESS_DESCRIPTION *);
diff --git a/src/_cffi_src/utils.py b/src/_cffi_src/utils.py
index d3dd18a4e..56745a3e5 100644
--- a/src/_cffi_src/utils.py
+++ b/src/_cffi_src/utils.py
@@ -4,6 +4,7 @@
from __future__ import absolute_import, division, print_function
+import os
import sys
from distutils.ccompiler import new_compiler
from distutils.dist import Distribution
@@ -11,8 +12,21 @@ from distutils.dist import Distribution
from cffi import FFI
-def build_ffi_for_binding(module_name, module_prefix, modules, libraries=[],
- extra_compile_args=[], extra_link_args=[]):
+# Load the cryptography __about__ to get the current package version
+base_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+about = {}
+with open(os.path.join(base_src, "cryptography", "__about__.py")) as f:
+ exec (f.read(), about)
+
+
+def build_ffi_for_binding(
+ module_name,
+ module_prefix,
+ modules,
+ libraries=[],
+ extra_compile_args=[],
+ extra_link_args=[],
+):
"""
Modules listed in ``modules`` should have the following attributes:
@@ -36,10 +50,7 @@ def build_ffi_for_binding(module_name, module_prefix, modules, libraries=[],
includes.append(module.INCLUDES)
customizations.append(module.CUSTOMIZATIONS)
- verify_source = "\n".join(
- includes +
- customizations
- )
+ verify_source = "\n".join(includes + customizations)
ffi = build_ffi(
module_name,
cdef_source="\n".join(types + functions),
@@ -52,9 +63,20 @@ def build_ffi_for_binding(module_name, module_prefix, modules, libraries=[],
return ffi
-def build_ffi(module_name, cdef_source, verify_source, libraries=[],
- extra_compile_args=[], extra_link_args=[]):
+def build_ffi(
+ module_name,
+ cdef_source,
+ verify_source,
+ libraries=[],
+ extra_compile_args=[],
+ extra_link_args=[],
+):
ffi = FFI()
+ # Always add the CRYPTOGRAPHY_PACKAGE_VERSION to the shared object
+ cdef_source += "\nstatic const char *const CRYPTOGRAPHY_PACKAGE_VERSION;"
+ verify_source += '\n#define CRYPTOGRAPHY_PACKAGE_VERSION "{}"'.format(
+ about["__version__"]
+ )
ffi.cdef(cdef_source)
ffi.set_source(
module_name,
@@ -67,10 +89,10 @@ def build_ffi(module_name, cdef_source, verify_source, libraries=[],
def extra_link_args(compiler_type):
- if compiler_type == 'msvc':
+ if compiler_type == "msvc":
# Enable NX and ASLR for Windows builds on MSVC. These are enabled by
# default on Python 3.3+ but not on 2.x.
- return ['/NXCOMPAT', '/DYNAMICBASE']
+ return ["/NXCOMPAT", "/DYNAMICBASE"]
else:
return []
@@ -82,7 +104,7 @@ def compiler_type():
"""
dist = Distribution()
dist.parse_config_files()
- cmd = dist.get_command_obj('build')
+ cmd = dist.get_command_obj("build")
cmd.ensure_finalized()
compiler = new_compiler(compiler=cmd.compiler)
return compiler.compiler_type
diff --git a/src/cryptography/Android.bp b/src/cryptography/Android.bp
index 876fd3d48..9bf4b2241 100644
--- a/src/cryptography/Android.bp
+++ b/src/cryptography/Android.bp
@@ -37,12 +37,12 @@ python_library {
"hazmat/primitives/ciphers/*.py",
"hazmat/bindings/*.py",
"hazmat/bindings/openssl/*.py",
- "x509/*.py",
+ "x509/*.py",
],
version: {
py2: {
- enabled: true,
- },
+ enabled: true,
+ },
py3: {
enabled: true,
},
@@ -50,7 +50,6 @@ python_library {
libs: [
"py-asn1crypto",
"py-cffi",
- "py-enum34",
"py-ipaddress",
"py-six",
],
@@ -63,7 +62,6 @@ python_library {
filegroup {
name: "py-cryptography-libs",
srcs: [
- "hazmat/bindings/_constant_time.so",
"hazmat/bindings/_openssl.so",
"hazmat/bindings/_padding.so",
],
diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py
index 02f81f6e8..f81650925 100644
--- a/src/cryptography/__about__.py
+++ b/src/cryptography/__about__.py
@@ -5,19 +5,27 @@
from __future__ import absolute_import, division, print_function
__all__ = [
- "__title__", "__summary__", "__uri__", "__version__", "__author__",
- "__email__", "__license__", "__copyright__",
+ "__title__",
+ "__summary__",
+ "__uri__",
+ "__version__",
+ "__author__",
+ "__email__",
+ "__license__",
+ "__copyright__",
]
__title__ = "cryptography"
-__summary__ = ("cryptography is a package which provides cryptographic recipes"
- " and primitives to Python developers.")
+__summary__ = (
+ "cryptography is a package which provides cryptographic recipes"
+ " and primitives to Python developers."
+)
__uri__ = "https://github.com/pyca/cryptography"
-__version__ = "2.5"
+__version__ = "3.3.2"
__author__ = "The cryptography developers"
__email__ = "cryptography-dev@python.org"
__license__ = "BSD or Apache License, Version 2.0"
-__copyright__ = "Copyright 2013-2017 {0}".format(__author__)
+__copyright__ = "Copyright 2013-2021 {}".format(__author__)
diff --git a/src/cryptography/__init__.py b/src/cryptography/__init__.py
index 6da0b3830..465671eec 100644
--- a/src/cryptography/__init__.py
+++ b/src/cryptography/__init__.py
@@ -4,13 +4,38 @@
from __future__ import absolute_import, division, print_function
+import sys
+import warnings
+
from cryptography.__about__ import (
- __author__, __copyright__, __email__, __license__, __summary__, __title__,
- __uri__, __version__
+ __author__,
+ __copyright__,
+ __email__,
+ __license__,
+ __summary__,
+ __title__,
+ __uri__,
+ __version__,
)
+from cryptography.utils import CryptographyDeprecationWarning
__all__ = [
- "__title__", "__summary__", "__uri__", "__version__", "__author__",
- "__email__", "__license__", "__copyright__",
+ "__title__",
+ "__summary__",
+ "__uri__",
+ "__version__",
+ "__author__",
+ "__email__",
+ "__license__",
+ "__copyright__",
]
+
+if sys.version_info[0] == 2:
+ warnings.warn(
+ "Python 2 is no longer supported by the Python core team. Support for "
+ "it is now deprecated in cryptography, and will be removed in the "
+ "next release.",
+ CryptographyDeprecationWarning,
+ stacklevel=2,
+ )
diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py
index 648cf9dfe..1d52d7dcf 100644
--- a/src/cryptography/exceptions.py
+++ b/src/cryptography/exceptions.py
@@ -19,6 +19,7 @@ class _Reasons(Enum):
UNSUPPORTED_X509 = 8
UNSUPPORTED_EXCHANGE_ALGORITHM = 9
UNSUPPORTED_DIFFIE_HELLMAN = 10
+ UNSUPPORTED_MAC = 11
class UnsupportedAlgorithm(Exception):
diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py
index b990defaa..00c252867 100644
--- a/src/cryptography/fernet.py
+++ b/src/cryptography/fernet.py
@@ -14,7 +14,7 @@ import six
from cryptography import utils
from cryptography.exceptions import InvalidSignature
-from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.primitives import hashes, padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.hmac import HMAC
@@ -29,8 +29,7 @@ _MAX_CLOCK_SKEW = 60
class Fernet(object):
def __init__(self, key, backend=None):
- if backend is None:
- backend = default_backend()
+ backend = _get_backend(backend)
key = base64.urlsafe_b64decode(key)
if len(key) != 32:
@@ -47,7 +46,9 @@ class Fernet(object):
return base64.urlsafe_b64encode(os.urandom(32))
def encrypt(self, data):
- current_time = int(time.time())
+ return self.encrypt_at_time(data, int(time.time()))
+
+ def encrypt_at_time(self, data, current_time):
iv = os.urandom(16)
return self._encrypt_from_parts(data, current_time, iv)
@@ -72,7 +73,15 @@ class Fernet(object):
def decrypt(self, token, ttl=None):
timestamp, data = Fernet._get_unverified_token_data(token)
- return self._decrypt_data(data, timestamp, ttl)
+ return self._decrypt_data(data, timestamp, ttl, int(time.time()))
+
+ def decrypt_at_time(self, token, ttl, current_time):
+ if ttl is None:
+ raise ValueError(
+ "decrypt_at_time() can only be used with a non-None ttl"
+ )
+ timestamp, data = Fernet._get_unverified_token_data(token)
+ return self._decrypt_data(data, timestamp, ttl, current_time)
def extract_timestamp(self, token):
timestamp, data = Fernet._get_unverified_token_data(token)
@@ -92,7 +101,7 @@ class Fernet(object):
raise InvalidToken
try:
- timestamp, = struct.unpack(">Q", data[1:9])
+ (timestamp,) = struct.unpack(">Q", data[1:9])
except struct.error:
raise InvalidToken
return timestamp, data
@@ -105,8 +114,7 @@ class Fernet(object):
except InvalidSignature:
raise InvalidToken
- def _decrypt_data(self, data, timestamp, ttl):
- current_time = int(time.time())
+ def _decrypt_data(self, data, timestamp, ttl, current_time):
if ttl is not None:
if timestamp + ttl < current_time:
raise InvalidToken
@@ -146,13 +154,16 @@ class MultiFernet(object):
self._fernets = fernets
def encrypt(self, msg):
- return self._fernets[0].encrypt(msg)
+ return self.encrypt_at_time(msg, int(time.time()))
+
+ def encrypt_at_time(self, msg, current_time):
+ return self._fernets[0].encrypt_at_time(msg, current_time)
def rotate(self, msg):
timestamp, data = Fernet._get_unverified_token_data(msg)
for f in self._fernets:
try:
- p = f._decrypt_data(data, timestamp, None)
+ p = f._decrypt_data(data, timestamp, None, None)
break
except InvalidToken:
pass
@@ -169,3 +180,11 @@ class MultiFernet(object):
except InvalidToken:
pass
raise InvalidToken
+
+ def decrypt_at_time(self, msg, ttl, current_time):
+ for f in self._fernets:
+ try:
+ return f.decrypt_at_time(msg, ttl, current_time)
+ except InvalidToken:
+ pass
+ raise InvalidToken
diff --git a/src/cryptography/hazmat/_der.py b/src/cryptography/hazmat/_der.py
new file mode 100644
index 000000000..462b911b4
--- /dev/null
+++ b/src/cryptography/hazmat/_der.py
@@ -0,0 +1,156 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import six
+
+from cryptography.utils import int_from_bytes, int_to_bytes
+
+
+# This module contains a lightweight DER encoder and decoder. See X.690 for the
+# specification. This module intentionally does not implement the more complex
+# BER encoding, only DER.
+#
+# Note this implementation treats an element's constructed bit as part of the
+# tag. This is fine for DER, where the bit is always computable from the type.
+
+
+CONSTRUCTED = 0x20
+CONTEXT_SPECIFIC = 0x80
+
+INTEGER = 0x02
+BIT_STRING = 0x03
+OCTET_STRING = 0x04
+NULL = 0x05
+OBJECT_IDENTIFIER = 0x06
+SEQUENCE = 0x10 | CONSTRUCTED
+SET = 0x11 | CONSTRUCTED
+PRINTABLE_STRING = 0x13
+UTC_TIME = 0x17
+GENERALIZED_TIME = 0x18
+
+
+class DERReader(object):
+ def __init__(self, data):
+ self.data = memoryview(data)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, tb):
+ if exc_value is None:
+ self.check_empty()
+
+ def is_empty(self):
+ return len(self.data) == 0
+
+ def check_empty(self):
+ if not self.is_empty():
+ raise ValueError("Invalid DER input: trailing data")
+
+ def read_byte(self):
+ if len(self.data) < 1:
+ raise ValueError("Invalid DER input: insufficient data")
+ ret = six.indexbytes(self.data, 0)
+ self.data = self.data[1:]
+ return ret
+
+ def read_bytes(self, n):
+ if len(self.data) < n:
+ raise ValueError("Invalid DER input: insufficient data")
+ ret = self.data[:n]
+ self.data = self.data[n:]
+ return ret
+
+ def read_any_element(self):
+ tag = self.read_byte()
+ # Tag numbers 31 or higher are stored in multiple bytes. No supported
+ # ASN.1 types use such tags, so reject these.
+ if tag & 0x1F == 0x1F:
+ raise ValueError("Invalid DER input: unexpected high tag number")
+ length_byte = self.read_byte()
+ if length_byte & 0x80 == 0:
+ # If the high bit is clear, the first length byte is the length.
+ length = length_byte
+ else:
+ # If the high bit is set, the first length byte encodes the length
+ # of the length.
+ length_byte &= 0x7F
+ if length_byte == 0:
+ raise ValueError(
+ "Invalid DER input: indefinite length form is not allowed "
+ "in DER"
+ )
+ length = 0
+ for i in range(length_byte):
+ length <<= 8
+ length |= self.read_byte()
+ if length == 0:
+ raise ValueError(
+ "Invalid DER input: length was not minimally-encoded"
+ )
+ if length < 0x80:
+ # If the length could have been encoded in short form, it must
+ # not use long form.
+ raise ValueError(
+ "Invalid DER input: length was not minimally-encoded"
+ )
+ body = self.read_bytes(length)
+ return tag, DERReader(body)
+
+ def read_element(self, expected_tag):
+ tag, body = self.read_any_element()
+ if tag != expected_tag:
+ raise ValueError("Invalid DER input: unexpected tag")
+ return body
+
+ def read_single_element(self, expected_tag):
+ with self:
+ return self.read_element(expected_tag)
+
+ def read_optional_element(self, expected_tag):
+ if len(self.data) > 0 and six.indexbytes(self.data, 0) == expected_tag:
+ return self.read_element(expected_tag)
+ return None
+
+ def as_integer(self):
+ if len(self.data) == 0:
+ raise ValueError("Invalid DER input: empty integer contents")
+ first = six.indexbytes(self.data, 0)
+ if first & 0x80 == 0x80:
+ raise ValueError("Negative DER integers are not supported")
+ # The first 9 bits must not all be zero or all be ones. Otherwise, the
+ # encoding should have been one byte shorter.
+ if len(self.data) > 1:
+ second = six.indexbytes(self.data, 1)
+ if first == 0 and second & 0x80 == 0:
+ raise ValueError(
+ "Invalid DER input: integer not minimally-encoded"
+ )
+ return int_from_bytes(self.data, "big")
+
+
+def encode_der_integer(x):
+ if not isinstance(x, six.integer_types):
+ raise ValueError("Value must be an integer")
+ if x < 0:
+ raise ValueError("Negative integers are not supported")
+ n = x.bit_length() // 8 + 1
+ return int_to_bytes(x, n)
+
+
+def encode_der(tag, *children):
+ length = 0
+ for child in children:
+ length += len(child)
+ chunks = [six.int2byte(tag)]
+ if length < 0x80:
+ chunks.append(six.int2byte(length))
+ else:
+ length_bytes = int_to_bytes(length)
+ chunks.append(six.int2byte(0x80 | len(length_bytes)))
+ chunks.append(length_bytes)
+ chunks.extend(children)
+ return b"".join(chunks)
diff --git a/src/cryptography/hazmat/_oid.py b/src/cryptography/hazmat/_oid.py
index cfe906cd3..de2771a73 100644
--- a/src/cryptography/hazmat/_oid.py
+++ b/src/cryptography/hazmat/_oid.py
@@ -19,26 +19,36 @@ class ObjectIdentifier(object):
# range 0..39. All nodes must be integers.
for node in nodes:
try:
- intnodes.append(int(node, 0))
+ node_value = int(node, 10)
except ValueError:
raise ValueError(
- "Malformed OID: %s (non-integer nodes)" % (
- self._dotted_string))
+ "Malformed OID: %s (non-integer nodes)"
+ % (self._dotted_string)
+ )
+ if node_value < 0:
+ raise ValueError(
+ "Malformed OID: %s (negative-integer nodes)"
+ % (self._dotted_string)
+ )
+ intnodes.append(node_value)
if len(nodes) < 2:
raise ValueError(
- "Malformed OID: %s (insufficient number of nodes)" % (
- self._dotted_string))
+ "Malformed OID: %s (insufficient number of nodes)"
+ % (self._dotted_string)
+ )
if intnodes[0] > 2:
raise ValueError(
- "Malformed OID: %s (first node outside valid range)" % (
- self._dotted_string))
+ "Malformed OID: %s (first node outside valid range)"
+ % (self._dotted_string)
+ )
if intnodes[0] < 2 and intnodes[1] >= 40:
raise ValueError(
- "Malformed OID: %s (second node outside valid range)" % (
- self._dotted_string))
+ "Malformed OID: %s (second node outside valid range)"
+ % (self._dotted_string)
+ )
def __eq__(self, other):
if not isinstance(other, ObjectIdentifier):
@@ -50,9 +60,8 @@ class ObjectIdentifier(object):
return not self == other
def __repr__(self):
- return "<ObjectIdentifier(oid={0}, name={1})>".format(
- self.dotted_string,
- self._name
+ return "<ObjectIdentifier(oid={}, name={})>".format(
+ self.dotted_string, self._name
)
def __hash__(self):
@@ -62,6 +71,7 @@ class ObjectIdentifier(object):
def _name(self):
# Lazy import to avoid an import cycle
from cryptography.x509.oid import _OID_NAMES
+
return _OID_NAMES.get(self, "Unknown OID")
dotted_string = utils.read_only_property("_dotted_string")
diff --git a/src/cryptography/hazmat/backends/__init__.py b/src/cryptography/hazmat/backends/__init__.py
index 565bde788..1563936dd 100644
--- a/src/cryptography/hazmat/backends/__init__.py
+++ b/src/cryptography/hazmat/backends/__init__.py
@@ -13,6 +13,14 @@ def default_backend():
if _default_backend is None:
from cryptography.hazmat.backends.openssl.backend import backend
+
_default_backend = backend
return _default_backend
+
+
+def _get_backend(backend):
+ if backend is None:
+ return default_backend()
+ else:
+ return backend
diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py
index 0a476b991..418980a34 100644
--- a/src/cryptography/hazmat/backends/interfaces.py
+++ b/src/cryptography/hazmat/backends/interfaces.py
@@ -57,7 +57,7 @@ class HMACBackend(object):
@abc.abstractmethod
def create_hmac_ctx(self, key, algorithm):
"""
- Create a MACContext for calculating a message authentication code.
+ Create a context for calculating a message authentication code.
"""
@@ -72,7 +72,7 @@ class CMACBackend(object):
@abc.abstractmethod
def create_cmac_ctx(self, algorithm):
"""
- Create a MACContext for calculating a message authentication code.
+ Create a context for calculating a message authentication code.
"""
@@ -86,8 +86,9 @@ class PBKDF2HMACBackend(object):
"""
@abc.abstractmethod
- def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations,
- key_material):
+ def derive_pbkdf2_hmac(
+ self, algorithm, length, salt, iterations, key_material
+ ):
"""
Return length bytes derived from provided PBKDF2 parameters.
"""
diff --git a/src/cryptography/hazmat/backends/openssl/aead.py b/src/cryptography/hazmat/backends/openssl/aead.py
index 73195ff3e..449491685 100644
--- a/src/cryptography/hazmat/backends/openssl/aead.py
+++ b/src/cryptography/hazmat/backends/openssl/aead.py
@@ -13,15 +13,18 @@ _DECRYPT = 0
def _aead_cipher_name(cipher):
from cryptography.hazmat.primitives.ciphers.aead import (
- AESCCM, AESGCM, ChaCha20Poly1305
+ AESCCM,
+ AESGCM,
+ ChaCha20Poly1305,
)
+
if isinstance(cipher, ChaCha20Poly1305):
return b"chacha20-poly1305"
elif isinstance(cipher, AESCCM):
- return "aes-{0}-ccm".format(len(cipher._key) * 8).encode("ascii")
+ return "aes-{}-ccm".format(len(cipher._key) * 8).encode("ascii")
else:
assert isinstance(cipher, AESGCM)
- return "aes-{0}-gcm".format(len(cipher._key) * 8).encode("ascii")
+ return "aes-{}-gcm".format(len(cipher._key) * 8).encode("ascii")
def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):
@@ -30,18 +33,21 @@ def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):
ctx = backend._lib.EVP_CIPHER_CTX_new()
ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free)
res = backend._lib.EVP_CipherInit_ex(
- ctx, evp_cipher,
+ ctx,
+ evp_cipher,
backend._ffi.NULL,
backend._ffi.NULL,
backend._ffi.NULL,
- int(operation == _ENCRYPT)
+ int(operation == _ENCRYPT),
)
backend.openssl_assert(res != 0)
res = backend._lib.EVP_CIPHER_CTX_set_key_length(ctx, len(key))
backend.openssl_assert(res != 0)
res = backend._lib.EVP_CIPHER_CTX_ctrl(
- ctx, backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(nonce),
- backend._ffi.NULL
+ ctx,
+ backend._lib.EVP_CTRL_AEAD_SET_IVLEN,
+ len(nonce),
+ backend._ffi.NULL,
)
backend.openssl_assert(res != 0)
if operation == _DECRYPT:
@@ -49,10 +55,11 @@ def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):
ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag
)
backend.openssl_assert(res != 0)
- else:
+ elif cipher_name.endswith(b"-ccm"):
res = backend._lib.EVP_CIPHER_CTX_ctrl(
ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, tag_len, backend._ffi.NULL
)
+ backend.openssl_assert(res != 0)
nonce_ptr = backend._ffi.from_buffer(nonce)
key_ptr = backend._ffi.from_buffer(key)
@@ -62,7 +69,7 @@ def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):
backend._ffi.NULL,
key_ptr,
nonce_ptr,
- int(operation == _ENCRYPT)
+ int(operation == _ENCRYPT),
)
backend.openssl_assert(res != 0)
return ctx
@@ -71,11 +78,7 @@ def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):
def _set_length(backend, ctx, data_len):
intptr = backend._ffi.new("int *")
res = backend._lib.EVP_CipherUpdate(
- ctx,
- backend._ffi.NULL,
- intptr,
- backend._ffi.NULL,
- data_len
+ ctx, backend._ffi.NULL, intptr, backend._ffi.NULL, data_len
)
backend.openssl_assert(res != 0)
@@ -98,6 +101,7 @@ def _process_data(backend, ctx, data):
def _encrypt(backend, cipher, nonce, data, associated_data, tag_length):
from cryptography.hazmat.primitives.ciphers.aead import AESCCM
+
cipher_name = _aead_cipher_name(cipher)
ctx = _aead_setup(
backend, cipher_name, cipher._key, nonce, None, tag_length, _ENCRYPT
@@ -125,6 +129,7 @@ def _encrypt(backend, cipher, nonce, data, associated_data, tag_length):
def _decrypt(backend, cipher, nonce, data, associated_data, tag_length):
from cryptography.hazmat.primitives.ciphers.aead import AESCCM
+
if len(data) < tag_length:
raise InvalidTag
tag = data[-tag_length:]
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 0a9bc53ae..45d4a1a1e 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -4,84 +4,166 @@
from __future__ import absolute_import, division, print_function
-import base64
import collections
import contextlib
import itertools
+import warnings
from contextlib import contextmanager
-import asn1crypto.core
-
import six
from six.moves import range
from cryptography import utils, x509
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+from cryptography.hazmat._der import (
+ INTEGER,
+ NULL,
+ SEQUENCE,
+ encode_der,
+ encode_der_integer,
+)
from cryptography.hazmat.backends.interfaces import (
- CMACBackend, CipherBackend, DERSerializationBackend, DHBackend, DSABackend,
- EllipticCurveBackend, HMACBackend, HashBackend, PBKDF2HMACBackend,
- PEMSerializationBackend, RSABackend, ScryptBackend, X509Backend
+ CMACBackend,
+ CipherBackend,
+ DERSerializationBackend,
+ DHBackend,
+ DSABackend,
+ EllipticCurveBackend,
+ HMACBackend,
+ HashBackend,
+ PBKDF2HMACBackend,
+ PEMSerializationBackend,
+ RSABackend,
+ ScryptBackend,
+ X509Backend,
)
from cryptography.hazmat.backends.openssl import aead
from cryptography.hazmat.backends.openssl.ciphers import _CipherContext
from cryptography.hazmat.backends.openssl.cmac import _CMACContext
from cryptography.hazmat.backends.openssl.decode_asn1 import (
- _CRL_ENTRY_REASON_ENUM_TO_CODE, _Integers
+ _CRL_ENTRY_REASON_ENUM_TO_CODE,
+ _CRL_EXTENSION_HANDLERS,
+ _EXTENSION_HANDLERS_BASE,
+ _EXTENSION_HANDLERS_SCT,
+ _OCSP_BASICRESP_EXTENSION_HANDLERS,
+ _OCSP_REQ_EXTENSION_HANDLERS,
+ _OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT,
+ _REVOKED_EXTENSION_HANDLERS,
+ _X509ExtensionParser,
)
from cryptography.hazmat.backends.openssl.dh import (
- _DHParameters, _DHPrivateKey, _DHPublicKey, _dh_params_dup
+ _DHParameters,
+ _DHPrivateKey,
+ _DHPublicKey,
+ _dh_params_dup,
)
from cryptography.hazmat.backends.openssl.dsa import (
- _DSAParameters, _DSAPrivateKey, _DSAPublicKey
+ _DSAParameters,
+ _DSAPrivateKey,
+ _DSAPublicKey,
)
from cryptography.hazmat.backends.openssl.ec import (
- _EllipticCurvePrivateKey, _EllipticCurvePublicKey
+ _EllipticCurvePrivateKey,
+ _EllipticCurvePublicKey,
+)
+from cryptography.hazmat.backends.openssl.ed25519 import (
+ _Ed25519PrivateKey,
+ _Ed25519PublicKey,
+)
+from cryptography.hazmat.backends.openssl.ed448 import (
+ _ED448_KEY_SIZE,
+ _Ed448PrivateKey,
+ _Ed448PublicKey,
)
from cryptography.hazmat.backends.openssl.encode_asn1 import (
_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS,
- _CRL_EXTENSION_ENCODE_HANDLERS, _EXTENSION_ENCODE_HANDLERS,
+ _CRL_EXTENSION_ENCODE_HANDLERS,
+ _EXTENSION_ENCODE_HANDLERS,
_OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS,
_OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS,
- _encode_asn1_int_gc, _encode_asn1_str_gc, _encode_name_gc, _txt2obj_gc,
+ _encode_asn1_int_gc,
+ _encode_asn1_str_gc,
+ _encode_name_gc,
+ _txt2obj_gc,
)
from cryptography.hazmat.backends.openssl.hashes import _HashContext
from cryptography.hazmat.backends.openssl.hmac import _HMACContext
from cryptography.hazmat.backends.openssl.ocsp import (
- _OCSPRequest, _OCSPResponse
+ _OCSPRequest,
+ _OCSPResponse,
+)
+from cryptography.hazmat.backends.openssl.poly1305 import (
+ _POLY1305_KEY_SIZE,
+ _Poly1305Context,
)
from cryptography.hazmat.backends.openssl.rsa import (
- _RSAPrivateKey, _RSAPublicKey
+ _RSAPrivateKey,
+ _RSAPublicKey,
)
from cryptography.hazmat.backends.openssl.x25519 import (
- _X25519PrivateKey, _X25519PublicKey
+ _X25519PrivateKey,
+ _X25519PublicKey,
)
from cryptography.hazmat.backends.openssl.x448 import (
- _X448PrivateKey, _X448PublicKey
+ _X448PrivateKey,
+ _X448PublicKey,
)
from cryptography.hazmat.backends.openssl.x509 import (
- _Certificate, _CertificateRevocationList,
- _CertificateSigningRequest, _RevokedCertificate
+ _Certificate,
+ _CertificateRevocationList,
+ _CertificateSigningRequest,
+ _RevokedCertificate,
)
from cryptography.hazmat.bindings.openssl import binding
from cryptography.hazmat.primitives import hashes, serialization
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
+from cryptography.hazmat.primitives.asymmetric import (
+ dh,
+ dsa,
+ ec,
+ ed25519,
+ ed448,
+ rsa,
+)
from cryptography.hazmat.primitives.asymmetric.padding import (
- MGF1, OAEP, PKCS1v15, PSS
+ MGF1,
+ OAEP,
+ PKCS1v15,
+ PSS,
)
from cryptography.hazmat.primitives.ciphers.algorithms import (
- AES, ARC4, Blowfish, CAST5, Camellia, ChaCha20, IDEA, SEED, TripleDES
+ AES,
+ ARC4,
+ Blowfish,
+ CAST5,
+ Camellia,
+ ChaCha20,
+ IDEA,
+ SEED,
+ TripleDES,
)
from cryptography.hazmat.primitives.ciphers.modes import (
- CBC, CFB, CFB8, CTR, ECB, GCM, OFB, XTS
+ CBC,
+ CFB,
+ CFB8,
+ CTR,
+ ECB,
+ GCM,
+ OFB,
+ XTS,
)
from cryptography.hazmat.primitives.kdf import scrypt
-from cryptography.hazmat.primitives.serialization import ssh
+from cryptography.hazmat.primitives.serialization import pkcs7, ssh
from cryptography.x509 import ocsp
_MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"])
+# Not actually supported, just used as a marker for some serialization tests.
+class _RC2(object):
+ pass
+
+
@utils.register_interface(CipherBackend)
@utils.register_interface(CMACBackend)
@utils.register_interface(DERSerializationBackend)
@@ -101,39 +183,93 @@ class Backend(object):
"""
OpenSSL API binding interfaces.
"""
+
name = "openssl"
+ # FIPS has opinions about acceptable algorithms and key sizes, but the
+ # disallowed algorithms are still present in OpenSSL. They just error if
+ # you try to use them. To avoid that we allowlist the algorithms in
+ # FIPS 140-3. This isn't ideal, but FIPS 140-3 is trash so here we are.
+ _fips_aead = {
+ b"aes-128-ccm",
+ b"aes-192-ccm",
+ b"aes-256-ccm",
+ b"aes-128-gcm",
+ b"aes-192-gcm",
+ b"aes-256-gcm",
+ }
+ _fips_ciphers = (AES, TripleDES)
+ _fips_hashes = (
+ hashes.SHA1,
+ hashes.SHA224,
+ hashes.SHA256,
+ hashes.SHA384,
+ hashes.SHA512,
+ hashes.SHA512_224,
+ hashes.SHA512_256,
+ hashes.SHA3_224,
+ hashes.SHA3_256,
+ hashes.SHA3_384,
+ hashes.SHA3_512,
+ hashes.SHAKE128,
+ hashes.SHAKE256,
+ )
+ _fips_rsa_min_key_size = 2048
+ _fips_rsa_min_public_exponent = 65537
+ _fips_dsa_min_modulus = 1 << 2048
+ _fips_dh_min_key_size = 2048
+ _fips_dh_min_modulus = 1 << _fips_dh_min_key_size
+
def __init__(self):
self._binding = binding.Binding()
self._ffi = self._binding.ffi
self._lib = self._binding.lib
+ self._fips_enabled = self._is_fips_enabled()
self._cipher_registry = {}
self._register_default_ciphers()
- self.activate_osrandom_engine()
+ self._register_x509_ext_parsers()
+ self._register_x509_encoders()
+ if self._fips_enabled and self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE:
+ warnings.warn(
+ "OpenSSL FIPS mode is enabled. Can't enable DRBG fork safety.",
+ UserWarning,
+ )
+ else:
+ self.activate_osrandom_engine()
self._dh_types = [self._lib.EVP_PKEY_DH]
if self._lib.Cryptography_HAS_EVP_PKEY_DHX:
self._dh_types.append(self._lib.EVP_PKEY_DHX)
- def openssl_assert(self, ok):
- return binding._openssl_assert(self._lib, ok)
+ def openssl_assert(self, ok, errors=None):
+ return binding._openssl_assert(self._lib, ok, errors=errors)
+
+ def _is_fips_enabled(self):
+ fips_mode = getattr(self._lib, "FIPS_mode", lambda: 0)
+ mode = fips_mode()
+ if mode == 0:
+ # OpenSSL without FIPS pushes an error on the error stack
+ self._lib.ERR_clear_error()
+ return bool(mode)
def activate_builtin_random(self):
- # Obtain a new structural reference.
- e = self._lib.ENGINE_get_default_RAND()
- if e != self._ffi.NULL:
- self._lib.ENGINE_unregister_RAND(e)
- # Reset the RNG to use the new engine.
- self._lib.RAND_cleanup()
- # decrement the structural reference from get_default_RAND
- res = self._lib.ENGINE_finish(e)
- self.openssl_assert(res == 1)
+ if self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE:
+ # Obtain a new structural reference.
+ e = self._lib.ENGINE_get_default_RAND()
+ if e != self._ffi.NULL:
+ self._lib.ENGINE_unregister_RAND(e)
+ # Reset the RNG to use the built-in.
+ res = self._lib.RAND_set_rand_method(self._ffi.NULL)
+ self.openssl_assert(res == 1)
+ # decrement the structural reference from get_default_RAND
+ res = self._lib.ENGINE_finish(e)
+ self.openssl_assert(res == 1)
@contextlib.contextmanager
def _get_osurandom_engine(self):
# Fetches an engine by id and returns it. This creates a structural
# reference.
- e = self._lib.ENGINE_by_id(self._binding._osrandom_engine_id)
+ e = self._lib.ENGINE_by_id(self._lib.Cryptography_osrandom_engine_id)
self.openssl_assert(e != self._ffi.NULL)
# Initialize the engine for use. This adds a functional reference.
res = self._lib.ENGINE_init(e)
@@ -150,30 +286,32 @@ class Backend(object):
self.openssl_assert(res == 1)
def activate_osrandom_engine(self):
- # Unregister and free the current engine.
- self.activate_builtin_random()
- with self._get_osurandom_engine() as e:
- # Set the engine as the default RAND provider.
- res = self._lib.ENGINE_set_default_RAND(e)
+ if self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE:
+ # Unregister and free the current engine.
+ self.activate_builtin_random()
+ with self._get_osurandom_engine() as e:
+ # Set the engine as the default RAND provider.
+ res = self._lib.ENGINE_set_default_RAND(e)
+ self.openssl_assert(res == 1)
+ # Reset the RNG to use the engine
+ res = self._lib.RAND_set_rand_method(self._ffi.NULL)
self.openssl_assert(res == 1)
- # Reset the RNG to use the new engine.
- self._lib.RAND_cleanup()
def osrandom_engine_implementation(self):
buf = self._ffi.new("char[]", 64)
with self._get_osurandom_engine() as e:
- res = self._lib.ENGINE_ctrl_cmd(e, b"get_implementation",
- len(buf), buf,
- self._ffi.NULL, 0)
+ res = self._lib.ENGINE_ctrl_cmd(
+ e, b"get_implementation", len(buf), buf, self._ffi.NULL, 0
+ )
self.openssl_assert(res > 0)
- return self._ffi.string(buf).decode('ascii')
+ return self._ffi.string(buf).decode("ascii")
def openssl_version_text(self):
"""
Friendly string name of the loaded OpenSSL library. This is not
necessarily the same version as it was compiled against.
- Example: OpenSSL 1.0.1e 11 Feb 2013
+ Example: OpenSSL 1.1.1d 10 Sep 2019
"""
return self._ffi.string(
self._lib.OpenSSL_version(self._lib.OPENSSL_VERSION)
@@ -187,7 +325,7 @@ class Backend(object):
def _evp_md_from_algorithm(self, algorithm):
if algorithm.name == "blake2b" or algorithm.name == "blake2s":
- alg = "{0}{1}".format(
+ alg = "{}{}".format(
algorithm.name, algorithm.digest_size * 8
).encode("ascii")
else:
@@ -202,6 +340,9 @@ class Backend(object):
return evp_md
def hash_supported(self, algorithm):
+ if self._fips_enabled and not isinstance(algorithm, self._fips_hashes):
+ return False
+
evp_md = self._evp_md_from_algorithm(algorithm)
return evp_md != self._ffi.NULL
@@ -212,6 +353,8 @@ class Backend(object):
return _HashContext(self, algorithm)
def cipher_supported(self, cipher, mode):
+ if self._fips_enabled and not isinstance(cipher, self._fips_ciphers):
+ return False
try:
adapter = self._cipher_registry[type(cipher), type(mode)]
except KeyError:
@@ -221,8 +364,10 @@ class Backend(object):
def register_cipher_adapter(self, cipher_cls, mode_cls, adapter):
if (cipher_cls, mode_cls) in self._cipher_registry:
- raise ValueError("Duplicate registration for: {0} {1}.".format(
- cipher_cls, mode_cls)
+ raise ValueError(
+ "Duplicate registration for: {} {}.".format(
+ cipher_cls, mode_cls
+ )
)
self._cipher_registry[cipher_cls, mode_cls] = adapter
@@ -231,36 +376,28 @@ class Backend(object):
self.register_cipher_adapter(
AES,
mode_cls,
- GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}")
+ GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}"),
)
for mode_cls in [CBC, CTR, ECB, OFB, CFB]:
self.register_cipher_adapter(
Camellia,
mode_cls,
- GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}")
+ GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}"),
)
for mode_cls in [CBC, CFB, CFB8, OFB]:
self.register_cipher_adapter(
- TripleDES,
- mode_cls,
- GetCipherByName("des-ede3-{mode.name}")
+ TripleDES, mode_cls, GetCipherByName("des-ede3-{mode.name}")
)
self.register_cipher_adapter(
- TripleDES,
- ECB,
- GetCipherByName("des-ede3")
+ TripleDES, ECB, GetCipherByName("des-ede3")
)
for mode_cls in [CBC, CFB, OFB, ECB]:
self.register_cipher_adapter(
- Blowfish,
- mode_cls,
- GetCipherByName("bf-{mode.name}")
+ Blowfish, mode_cls, GetCipherByName("bf-{mode.name}")
)
for mode_cls in [CBC, CFB, OFB, ECB]:
self.register_cipher_adapter(
- SEED,
- mode_cls,
- GetCipherByName("seed-{mode.name}")
+ SEED, mode_cls, GetCipherByName("seed-{mode.name}")
)
for cipher_cls, mode_cls in itertools.product(
[CAST5, IDEA],
@@ -269,20 +406,84 @@ class Backend(object):
self.register_cipher_adapter(
cipher_cls,
mode_cls,
- GetCipherByName("{cipher.name}-{mode.name}")
+ GetCipherByName("{cipher.name}-{mode.name}"),
)
+ self.register_cipher_adapter(ARC4, type(None), GetCipherByName("rc4"))
+ # We don't actually support RC2, this is just used by some tests.
+ self.register_cipher_adapter(_RC2, type(None), GetCipherByName("rc2"))
self.register_cipher_adapter(
- ARC4,
- type(None),
- GetCipherByName("rc4")
- )
- self.register_cipher_adapter(
- ChaCha20,
- type(None),
- GetCipherByName("chacha20")
+ ChaCha20, type(None), GetCipherByName("chacha20")
)
self.register_cipher_adapter(AES, XTS, _get_xts_cipher)
+ def _register_x509_ext_parsers(self):
+ ext_handlers = _EXTENSION_HANDLERS_BASE.copy()
+ # All revoked extensions are valid single response extensions, see:
+ # https://tools.ietf.org/html/rfc6960#section-4.4.5
+ singleresp_handlers = _REVOKED_EXTENSION_HANDLERS.copy()
+
+ if self._lib.Cryptography_HAS_SCT:
+ ext_handlers.update(_EXTENSION_HANDLERS_SCT)
+ singleresp_handlers.update(_OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT)
+
+ self._certificate_extension_parser = _X509ExtensionParser(
+ self,
+ ext_count=self._lib.X509_get_ext_count,
+ get_ext=self._lib.X509_get_ext,
+ handlers=ext_handlers,
+ )
+ self._csr_extension_parser = _X509ExtensionParser(
+ self,
+ ext_count=self._lib.sk_X509_EXTENSION_num,
+ get_ext=self._lib.sk_X509_EXTENSION_value,
+ handlers=ext_handlers,
+ )
+ self._revoked_cert_extension_parser = _X509ExtensionParser(
+ self,
+ ext_count=self._lib.X509_REVOKED_get_ext_count,
+ get_ext=self._lib.X509_REVOKED_get_ext,
+ handlers=_REVOKED_EXTENSION_HANDLERS,
+ )
+ self._crl_extension_parser = _X509ExtensionParser(
+ self,
+ ext_count=self._lib.X509_CRL_get_ext_count,
+ get_ext=self._lib.X509_CRL_get_ext,
+ handlers=_CRL_EXTENSION_HANDLERS,
+ )
+ self._ocsp_req_ext_parser = _X509ExtensionParser(
+ self,
+ ext_count=self._lib.OCSP_REQUEST_get_ext_count,
+ get_ext=self._lib.OCSP_REQUEST_get_ext,
+ handlers=_OCSP_REQ_EXTENSION_HANDLERS,
+ )
+ self._ocsp_basicresp_ext_parser = _X509ExtensionParser(
+ self,
+ ext_count=self._lib.OCSP_BASICRESP_get_ext_count,
+ get_ext=self._lib.OCSP_BASICRESP_get_ext,
+ handlers=_OCSP_BASICRESP_EXTENSION_HANDLERS,
+ )
+ self._ocsp_singleresp_ext_parser = _X509ExtensionParser(
+ self,
+ ext_count=self._lib.OCSP_SINGLERESP_get_ext_count,
+ get_ext=self._lib.OCSP_SINGLERESP_get_ext,
+ handlers=singleresp_handlers,
+ )
+
+ def _register_x509_encoders(self):
+ self._extension_encode_handlers = _EXTENSION_ENCODE_HANDLERS.copy()
+ self._crl_extension_encode_handlers = (
+ _CRL_EXTENSION_ENCODE_HANDLERS.copy()
+ )
+ self._crl_entry_extension_encode_handlers = (
+ _CRL_ENTRY_EXTENSION_ENCODE_HANDLERS.copy()
+ )
+ self._ocsp_request_extension_encode_handlers = (
+ _OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS.copy()
+ )
+ self._ocsp_basicresp_extension_encode_handlers = (
+ _OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS.copy()
+ )
+
def create_symmetric_encryption_ctx(self, cipher, mode):
return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT)
@@ -292,8 +493,9 @@ class Backend(object):
def pbkdf2_hmac_supported(self, algorithm):
return self.hmac_supported(algorithm)
- def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations,
- key_material):
+ def derive_pbkdf2_hmac(
+ self, algorithm, length, salt, iterations, key_material
+ ):
buf = self._ffi.new("unsigned char[]", length)
evp_md = self._evp_md_non_null_from_algorithm(algorithm)
key_material_ptr = self._ffi.from_buffer(key_material)
@@ -305,7 +507,7 @@ class Backend(object):
iterations,
evp_md,
length,
- buf
+ buf,
)
self.openssl_assert(res == 1)
return self._ffi.buffer(buf)[:]
@@ -313,6 +515,9 @@ class Backend(object):
def _consume_errors(self):
return binding._consume_errors(self._lib)
+ def _consume_errors_with_text(self):
+ return binding._consume_errors_with_text(self._lib)
+
def _bn_to_int(self, bn):
assert bn != self._ffi.NULL
@@ -323,7 +528,10 @@ class Backend(object):
bin_len = self._lib.BN_bn2bin(bn, bin_ptr)
# A zero length means the BN has value 0
self.openssl_assert(bin_len >= 0)
- return int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big")
+ val = int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big")
+ if self._lib.BN_is_negative(bn):
+ val = -val
+ return val
else:
# Under Python 2 the best we can do is hex()
hex_cdata = self._lib.BN_bn2hex(bn)
@@ -382,8 +590,11 @@ class Backend(object):
return _RSAPrivateKey(self, rsa_cdata, evp_pkey)
def generate_rsa_parameters_supported(self, public_exponent, key_size):
- return (public_exponent >= 3 and public_exponent & 1 != 0 and
- key_size >= 512)
+ return (
+ public_exponent >= 3
+ and public_exponent & 1 != 0
+ and key_size >= 512
+ )
def load_rsa_private_numbers(self, numbers):
rsa._check_private_key_components(
@@ -394,7 +605,7 @@ class Backend(object):
numbers.dmq1,
numbers.iqmp,
numbers.public_numbers.e,
- numbers.public_numbers.n
+ numbers.public_numbers.n,
)
rsa_cdata = self._lib.RSA_new()
self.openssl_assert(rsa_cdata != self._ffi.NULL)
@@ -413,8 +624,6 @@ class Backend(object):
self.openssl_assert(res == 1)
res = self._lib.RSA_set0_crt_params(rsa_cdata, dmp1, dmq1, iqmp)
self.openssl_assert(res == 1)
- res = self._lib.RSA_blinding_on(rsa_cdata, self._ffi.NULL)
- self.openssl_assert(res == 1)
evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata)
return _RSAPrivateKey(self, rsa_cdata, evp_pkey)
@@ -452,9 +661,7 @@ class Backend(object):
BIO is finished with.
"""
data_ptr = self._ffi.from_buffer(data)
- bio = self._lib.BIO_new_mem_buf(
- data_ptr, len(data)
- )
+ bio = self._lib.BIO_new_mem_buf(data_ptr, len(data))
self.openssl_assert(bio != self._ffi.NULL)
return _MemoryBIO(self._ffi.gc(bio, self._lib.BIO_free), data_ptr)
@@ -509,12 +716,18 @@ class Backend(object):
self.openssl_assert(dh_cdata != self._ffi.NULL)
dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
return _DHPrivateKey(self, dh_cdata, evp_pkey)
+ elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None):
+ # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1
+ return _Ed25519PrivateKey(self, evp_pkey)
elif key_type == getattr(self._lib, "EVP_PKEY_X448", None):
# EVP_PKEY_X448 is not present in OpenSSL < 1.1.1
return _X448PrivateKey(self, evp_pkey)
elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None):
# EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0
return _X25519PrivateKey(self, evp_pkey)
+ elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None):
+ # EVP_PKEY_ED448 is not present in OpenSSL < 1.1.1
+ return _Ed448PrivateKey(self, evp_pkey)
else:
raise UnsupportedAlgorithm("Unsupported key type.")
@@ -546,25 +759,32 @@ class Backend(object):
self.openssl_assert(dh_cdata != self._ffi.NULL)
dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
return _DHPublicKey(self, dh_cdata, evp_pkey)
+ elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None):
+ # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1
+ return _Ed25519PublicKey(self, evp_pkey)
elif key_type == getattr(self._lib, "EVP_PKEY_X448", None):
# EVP_PKEY_X448 is not present in OpenSSL < 1.1.1
return _X448PublicKey(self, evp_pkey)
elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None):
# EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0
return _X25519PublicKey(self, evp_pkey)
+ elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None):
+ # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.1
+ return _Ed448PublicKey(self, evp_pkey)
else:
raise UnsupportedAlgorithm("Unsupported key type.")
def _oaep_hash_supported(self, algorithm):
if self._lib.Cryptography_HAS_RSA_OAEP_MD:
return isinstance(
- algorithm, (
+ algorithm,
+ (
hashes.SHA1,
hashes.SHA224,
hashes.SHA256,
hashes.SHA384,
hashes.SHA512,
- )
+ ),
)
else:
return isinstance(algorithm, hashes.SHA1)
@@ -576,27 +796,34 @@ class Backend(object):
return self.hash_supported(padding._mgf._algorithm)
elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1):
return (
- self._oaep_hash_supported(padding._mgf._algorithm) and
- self._oaep_hash_supported(padding._algorithm) and
- (
- (padding._label is None or len(padding._label) == 0) or
- self._lib.Cryptography_HAS_RSA_OAEP_LABEL == 1
+ self._oaep_hash_supported(padding._mgf._algorithm)
+ and self._oaep_hash_supported(padding._algorithm)
+ and (
+ (padding._label is None or len(padding._label) == 0)
+ or self._lib.Cryptography_HAS_RSA_OAEP_LABEL == 1
)
)
else:
return False
def generate_dsa_parameters(self, key_size):
- if key_size not in (1024, 2048, 3072):
- raise ValueError("Key size must be 1024 or 2048 or 3072 bits.")
+ if key_size not in (1024, 2048, 3072, 4096):
+ raise ValueError(
+ "Key size must be 1024, 2048, 3072, or 4096 bits."
+ )
ctx = self._lib.DSA_new()
self.openssl_assert(ctx != self._ffi.NULL)
ctx = self._ffi.gc(ctx, self._lib.DSA_free)
res = self._lib.DSA_generate_parameters_ex(
- ctx, key_size, self._ffi.NULL, 0,
- self._ffi.NULL, self._ffi.NULL, self._ffi.NULL
+ ctx,
+ key_size,
+ self._ffi.NULL,
+ 0,
+ self._ffi.NULL,
+ self._ffi.NULL,
+ self._ffi.NULL,
)
self.openssl_assert(res == 1)
@@ -692,20 +919,37 @@ class Backend(object):
def create_cmac_ctx(self, algorithm):
return _CMACContext(self, algorithm)
- def create_x509_csr(self, builder, private_key, algorithm):
- if not isinstance(algorithm, hashes.HashAlgorithm):
- raise TypeError('Algorithm must be a registered hash algorithm.')
-
- if (
- isinstance(algorithm, hashes.MD5) and not
- isinstance(private_key, rsa.RSAPrivateKey)
+ def _x509_check_signature_params(self, private_key, algorithm):
+ if isinstance(
+ private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)
+ ):
+ if algorithm is not None:
+ raise ValueError(
+ "algorithm must be None when signing via ed25519 or ed448"
+ )
+ elif not isinstance(
+ private_key,
+ (rsa.RSAPrivateKey, dsa.DSAPrivateKey, ec.EllipticCurvePrivateKey),
+ ):
+ raise TypeError(
+ "Key must be an rsa, dsa, ec, ed25519, or ed448 private key."
+ )
+ elif not isinstance(algorithm, hashes.HashAlgorithm):
+ raise TypeError("Algorithm must be a registered hash algorithm.")
+ elif isinstance(algorithm, hashes.MD5) and not isinstance(
+ private_key, rsa.RSAPrivateKey
):
raise ValueError(
- "MD5 is not a supported hash algorithm for EC/DSA CSRs"
+ "MD5 hash algorithm is only supported with RSA keys"
)
+ def create_x509_csr(self, builder, private_key, algorithm):
+ if not isinstance(builder, x509.CertificateSigningRequestBuilder):
+ raise TypeError("Builder type mismatch.")
+ self._x509_check_signature_params(private_key, algorithm)
+
# Resolve the signature algorithm.
- evp_md = self._evp_md_non_null_from_algorithm(algorithm)
+ evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm)
# Create an empty request.
x509_req = self._lib.X509_REQ_new()
@@ -724,9 +968,7 @@ class Backend(object):
# Set subject public key.
public_key = private_key.public_key()
- res = self._lib.X509_REQ_set_pubkey(
- x509_req, public_key._evp_pkey
- )
+ res = self._lib.X509_REQ_set_pubkey(x509_req, public_key._evp_pkey)
self.openssl_assert(res == 1)
# Add extensions.
@@ -735,60 +977,55 @@ class Backend(object):
sk_extension = self._ffi.gc(
sk_extension,
lambda x: self._lib.sk_X509_EXTENSION_pop_free(
- x, self._ffi.addressof(
+ x,
+ self._ffi.addressof(
self._lib._original_lib, "X509_EXTENSION_free"
- )
- )
+ ),
+ ),
)
# Don't GC individual extensions because the memory is owned by
# sk_extensions and will be freed along with it.
self._create_x509_extensions(
extensions=builder._extensions,
- handlers=_EXTENSION_ENCODE_HANDLERS,
+ handlers=self._extension_encode_handlers,
x509_obj=sk_extension,
add_func=self._lib.sk_X509_EXTENSION_insert,
- gc=False
+ gc=False,
)
res = self._lib.X509_REQ_add_extensions(x509_req, sk_extension)
self.openssl_assert(res == 1)
- # Sign the request using the requester's private key.
- res = self._lib.X509_REQ_sign(
- x509_req, private_key._evp_pkey, evp_md
- )
- if res == 0:
- errors = self._consume_errors()
- self.openssl_assert(
- errors[0]._lib_reason_match(
- self._lib.ERR_LIB_RSA,
- self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY
- )
+ # Add attributes (all bytes encoded as ASN1 UTF8_STRING)
+ for attr_oid, attr_val in builder._attributes:
+ obj = _txt2obj_gc(self, attr_oid.dotted_string)
+ res = self._lib.X509_REQ_add1_attr_by_OBJ(
+ x509_req,
+ obj,
+ x509.name._ASN1Type.UTF8String.value,
+ attr_val,
+ len(attr_val),
)
+ self.openssl_assert(res == 1)
- raise ValueError("Digest too big for RSA key")
+ # Sign the request using the requester's private key.
+ res = self._lib.X509_REQ_sign(x509_req, private_key._evp_pkey, evp_md)
+ if res == 0:
+ errors = self._consume_errors_with_text()
+ raise ValueError("Signing failed", errors)
return _CertificateSigningRequest(self, x509_req)
def create_x509_certificate(self, builder, private_key, algorithm):
if not isinstance(builder, x509.CertificateBuilder):
- raise TypeError('Builder type mismatch.')
- if not isinstance(algorithm, hashes.HashAlgorithm):
- raise TypeError('Algorithm must be a registered hash algorithm.')
-
- if (
- isinstance(algorithm, hashes.MD5) and not
- isinstance(private_key, rsa.RSAPrivateKey)
- ):
- raise ValueError(
- "MD5 is not a supported hash algorithm for EC/DSA certificates"
- )
+ raise TypeError("Builder type mismatch.")
+ self._x509_check_signature_params(private_key, algorithm)
# Resolve the signature algorithm.
- evp_md = self._evp_md_non_null_from_algorithm(algorithm)
+ evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm)
# Create an empty certificate.
x509_cert = self._lib.X509_new()
- x509_cert = self._ffi.gc(x509_cert, backend._lib.X509_free)
+ x509_cert = self._ffi.gc(x509_cert, self._lib.X509_free)
# Set the x509 version.
res = self._lib.X509_set_version(x509_cert, builder._version.value)
@@ -813,21 +1050,21 @@ class Backend(object):
# Set the "not before" time.
self._set_asn1_time(
- self._lib.X509_get_notBefore(x509_cert), builder._not_valid_before
+ self._lib.X509_getm_notBefore(x509_cert), builder._not_valid_before
)
# Set the "not after" time.
self._set_asn1_time(
- self._lib.X509_get_notAfter(x509_cert), builder._not_valid_after
+ self._lib.X509_getm_notAfter(x509_cert), builder._not_valid_after
)
# Add extensions.
self._create_x509_extensions(
extensions=builder._extensions,
- handlers=_EXTENSION_ENCODE_HANDLERS,
+ handlers=self._extension_encode_handlers,
x509_obj=x509_cert,
add_func=self._lib.X509_add_ext,
- gc=True
+ gc=True,
)
# Set the issuer name.
@@ -837,26 +1074,27 @@ class Backend(object):
self.openssl_assert(res == 1)
# Sign the certificate with the issuer's private key.
- res = self._lib.X509_sign(
- x509_cert, private_key._evp_pkey, evp_md
- )
+ res = self._lib.X509_sign(x509_cert, private_key._evp_pkey, evp_md)
if res == 0:
- errors = self._consume_errors()
- self.openssl_assert(
- errors[0]._lib_reason_match(
- self._lib.ERR_LIB_RSA,
- self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY
- )
- )
- raise ValueError("Digest too big for RSA key")
+ errors = self._consume_errors_with_text()
+ raise ValueError("Signing failed", errors)
return _Certificate(self, x509_cert)
+ def _evp_md_x509_null_if_eddsa(self, private_key, algorithm):
+ if isinstance(
+ private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)
+ ):
+ # OpenSSL requires us to pass NULL for EVP_MD for ed25519/ed448
+ return self._ffi.NULL
+ else:
+ return self._evp_md_non_null_from_algorithm(algorithm)
+
def _set_asn1_time(self, asn1_time, time):
if time.year >= 2050:
- asn1_str = time.strftime('%Y%m%d%H%M%SZ').encode('ascii')
+ asn1_str = time.strftime("%Y%m%d%H%M%SZ").encode("ascii")
else:
- asn1_str = time.strftime('%y%m%d%H%M%SZ').encode('ascii')
+ asn1_str = time.strftime("%y%m%d%H%M%SZ").encode("ascii")
res = self._lib.ASN1_TIME_set_string(asn1_time, asn1_str)
self.openssl_assert(res == 1)
@@ -869,23 +1107,14 @@ class Backend(object):
def create_x509_crl(self, builder, private_key, algorithm):
if not isinstance(builder, x509.CertificateRevocationListBuilder):
- raise TypeError('Builder type mismatch.')
- if not isinstance(algorithm, hashes.HashAlgorithm):
- raise TypeError('Algorithm must be a registered hash algorithm.')
-
- if (
- isinstance(algorithm, hashes.MD5) and not
- isinstance(private_key, rsa.RSAPrivateKey)
- ):
- raise ValueError(
- "MD5 is not a supported hash algorithm for EC/DSA CRLs"
- )
+ raise TypeError("Builder type mismatch.")
+ self._x509_check_signature_params(private_key, algorithm)
- evp_md = self._evp_md_non_null_from_algorithm(algorithm)
+ evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm)
# Create an empty CRL.
x509_crl = self._lib.X509_CRL_new()
- x509_crl = self._ffi.gc(x509_crl, backend._lib.X509_CRL_free)
+ x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free)
# Set the x509 CRL version. We only support v2 (integer value 1).
res = self._lib.X509_CRL_set_version(x509_crl, 1)
@@ -910,44 +1139,33 @@ class Backend(object):
# Add extensions.
self._create_x509_extensions(
extensions=builder._extensions,
- handlers=_CRL_EXTENSION_ENCODE_HANDLERS,
+ handlers=self._crl_extension_encode_handlers,
x509_obj=x509_crl,
add_func=self._lib.X509_CRL_add_ext,
- gc=True
+ gc=True,
)
# add revoked certificates
for revoked_cert in builder._revoked_certificates:
# Duplicating because the X509_CRL takes ownership and will free
# this memory when X509_CRL_free is called.
- revoked = self._lib.Cryptography_X509_REVOKED_dup(
- revoked_cert._x509_revoked
- )
+ revoked = self._lib.X509_REVOKED_dup(revoked_cert._x509_revoked)
self.openssl_assert(revoked != self._ffi.NULL)
res = self._lib.X509_CRL_add0_revoked(x509_crl, revoked)
self.openssl_assert(res == 1)
- res = self._lib.X509_CRL_sign(
- x509_crl, private_key._evp_pkey, evp_md
- )
+ res = self._lib.X509_CRL_sign(x509_crl, private_key._evp_pkey, evp_md)
if res == 0:
- errors = self._consume_errors()
- self.openssl_assert(
- errors[0]._lib_reason_match(
- self._lib.ERR_LIB_RSA,
- self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY
- )
- )
- raise ValueError("Digest too big for RSA key")
+ errors = self._consume_errors_with_text()
+ raise ValueError("Signing failed", errors)
return _CertificateRevocationList(self, x509_crl)
- def _create_x509_extensions(self, extensions, handlers, x509_obj,
- add_func, gc):
+ def _create_x509_extensions(
+ self, extensions, handlers, x509_obj, add_func, gc
+ ):
for i, extension in enumerate(extensions):
- x509_extension = self._create_x509_extension(
- handlers, extension
- )
+ x509_extension = self._create_x509_extension(handlers, extension)
self.openssl_assert(x509_extension != self._ffi.NULL)
if gc:
@@ -968,33 +1186,38 @@ class Backend(object):
value = _encode_asn1_str_gc(self, extension.value.value)
return self._create_raw_x509_extension(extension, value)
elif isinstance(extension.value, x509.TLSFeature):
- asn1 = _Integers([x.value for x in extension.value]).dump()
+ asn1 = encode_der(
+ SEQUENCE,
+ *[
+ encode_der(INTEGER, encode_der_integer(x.value))
+ for x in extension.value
+ ]
+ )
value = _encode_asn1_str_gc(self, asn1)
return self._create_raw_x509_extension(extension, value)
elif isinstance(extension.value, x509.PrecertPoison):
- asn1 = asn1crypto.core.Null().dump()
- value = _encode_asn1_str_gc(self, asn1)
+ value = _encode_asn1_str_gc(self, encode_der(NULL))
return self._create_raw_x509_extension(extension, value)
else:
try:
encode = handlers[extension.oid]
except KeyError:
raise NotImplementedError(
- 'Extension not supported: {0}'.format(extension.oid)
+ "Extension not supported: {}".format(extension.oid)
)
ext_struct = encode(self, extension.value)
nid = self._lib.OBJ_txt2nid(
extension.oid.dotted_string.encode("ascii")
)
- backend.openssl_assert(nid != self._lib.NID_undef)
+ self.openssl_assert(nid != self._lib.NID_undef)
return self._lib.X509V3_EXT_i2d(
nid, 1 if extension.critical else 0, ext_struct
)
def create_x509_revoked_certificate(self, builder):
if not isinstance(builder, x509.RevokedCertificateBuilder):
- raise TypeError('Builder type mismatch.')
+ raise TypeError("Builder type mismatch.")
x509_revoked = self._lib.X509_REVOKED_new()
self.openssl_assert(x509_revoked != self._ffi.NULL)
@@ -1010,10 +1233,10 @@ class Backend(object):
# add CRL entry extensions
self._create_x509_extensions(
extensions=builder._extensions,
- handlers=_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS,
+ handlers=self._crl_entry_extension_encode_handlers,
x509_obj=x509_revoked,
add_func=self._lib.X509_REVOKED_add_ext,
- gc=True
+ gc=True,
)
return _RevokedCertificate(self, None, x509_revoked)
@@ -1054,7 +1277,8 @@ class Backend(object):
mem_bio = self._bytes_to_bio(data)
# only DH is supported currently
dh_cdata = self._lib.PEM_read_bio_DHparams(
- mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL)
+ mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL
+ )
if dh_cdata != self._ffi.NULL:
dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
return _DHParameters(self, dh_cdata)
@@ -1119,9 +1343,7 @@ class Backend(object):
def load_der_parameters(self, data):
mem_bio = self._bytes_to_bio(data)
- dh_cdata = self._lib.d2i_DHparams_bio(
- mem_bio.bio, self._ffi.NULL
- )
+ dh_cdata = self._lib.d2i_DHparams_bio(mem_bio.bio, self._ffi.NULL)
if dh_cdata != self._ffi.NULL:
dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free)
return _DHParameters(self, dh_cdata)
@@ -1147,8 +1369,9 @@ class Backend(object):
if x509 == self._ffi.NULL:
self._consume_errors()
raise ValueError(
- "Unable to load certificate. See https://cryptography.io/en/la"
- "test/faq/#why-can-t-i-import-my-pem-file for more details."
+ "Unable to load certificate. See https://cryptography.io/en/"
+ "latest/faq.html#why-can-t-i-import-my-pem-file for more"
+ " details."
)
x509 = self._ffi.gc(x509, self._lib.X509_free)
@@ -1173,7 +1396,8 @@ class Backend(object):
self._consume_errors()
raise ValueError(
"Unable to load CRL. See https://cryptography.io/en/la"
- "test/faq/#why-can-t-i-import-my-pem-file for more details."
+ "test/faq.html#why-can-t-i-import-my-pem-file for more"
+ " details."
)
x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free)
@@ -1197,8 +1421,9 @@ class Backend(object):
if x509_req == self._ffi.NULL:
self._consume_errors()
raise ValueError(
- "Unable to load request. See https://cryptography.io/en/la"
- "test/faq/#why-can-t-i-import-my-pem-file for more details."
+ "Unable to load request. See https://cryptography.io/en/"
+ "latest/faq.html#why-can-t-i-import-my-pem-file for more"
+ " details."
)
x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free)
@@ -1235,8 +1460,7 @@ class Backend(object):
if evp_pkey == self._ffi.NULL:
if userdata.error != 0:
- errors = self._consume_errors()
- self.openssl_assert(errors)
+ self._consume_errors()
if userdata.error == -1:
raise TypeError(
"Password was not given but private key is encrypted"
@@ -1244,7 +1468,7 @@ class Backend(object):
else:
assert userdata.error == -2
raise ValueError(
- "Passwords longer than {0} bytes are not supported "
+ "Passwords longer than {} bytes are not supported "
"by this backend.".format(userdata.maxsize - 1)
)
else:
@@ -1254,12 +1478,12 @@ class Backend(object):
if password is not None and userdata.called == 0:
raise TypeError(
- "Password was given but private key is not encrypted.")
+ "Password was given but private key is not encrypted."
+ )
assert (
- (password is not None and userdata.called == 1) or
- password is None
- )
+ password is not None and userdata.called == 1
+ ) or password is None
return convert_func(evp_pkey)
@@ -1267,46 +1491,34 @@ class Backend(object):
errors = self._consume_errors()
if not errors:
- raise ValueError("Could not deserialize key data.")
-
- elif (
- errors[0]._lib_reason_match(
- self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT
- ) or errors[0]._lib_reason_match(
- self._lib.ERR_LIB_PKCS12,
- self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR
+ raise ValueError(
+ "Could not deserialize key data. The data may be in an "
+ "incorrect format or it may be encrypted with an unsupported "
+ "algorithm."
)
+ elif errors[0]._lib_reason_match(
+ self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT
+ ) or errors[0]._lib_reason_match(
+ self._lib.ERR_LIB_PKCS12,
+ self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR,
):
raise ValueError("Bad decrypt. Incorrect password?")
- elif (
- errors[0]._lib_reason_match(
- self._lib.ERR_LIB_EVP, self._lib.EVP_R_UNKNOWN_PBE_ALGORITHM
- ) or errors[0]._lib_reason_match(
- self._lib.ERR_LIB_PEM, self._lib.PEM_R_UNSUPPORTED_ENCRYPTION
- )
- ):
- raise UnsupportedAlgorithm(
- "PEM data is encrypted with an unsupported cipher",
- _Reasons.UNSUPPORTED_CIPHER
- )
-
elif any(
error._lib_reason_match(
self._lib.ERR_LIB_EVP,
- self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM
+ self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM,
)
for error in errors
):
raise ValueError("Unsupported public key algorithm.")
else:
- assert errors[0].lib in (
- self._lib.ERR_LIB_EVP,
- self._lib.ERR_LIB_PEM,
- self._lib.ERR_LIB_ASN1,
+ raise ValueError(
+ "Could not deserialize key data. The data may be in an "
+ "incorrect format or it may be encrypted with an unsupported "
+ "algorithm."
)
- raise ValueError("Could not deserialize key data.")
def elliptic_curve_supported(self, curve):
try:
@@ -1317,14 +1529,7 @@ class Backend(object):
group = self._lib.EC_GROUP_new_by_curve_name(curve_nid)
if group == self._ffi.NULL:
- errors = self._consume_errors()
- self.openssl_assert(
- curve_nid == self._lib.NID_undef or
- errors[0]._lib_reason_match(
- self._lib.ERR_LIB_EC,
- self._lib.EC_R_UNKNOWN_GROUP
- )
- )
+ self._consume_errors()
return False
else:
self.openssl_assert(curve_nid != self._lib.NID_undef)
@@ -1356,8 +1561,8 @@ class Backend(object):
return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey)
else:
raise UnsupportedAlgorithm(
- "Backend object does not support {0}.".format(curve.name),
- _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+ "Backend object does not support {}.".format(curve.name),
+ _Reasons.UNSUPPORTED_ELLIPTIC_CURVE,
)
def load_elliptic_curve_private_numbers(self, numbers):
@@ -1372,7 +1577,8 @@ class Backend(object):
self.openssl_assert(res == 1)
ec_cdata = self._ec_key_set_public_key_affine_coordinates(
- ec_cdata, public.x, public.y)
+ ec_cdata, public.x, public.y
+ )
evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata)
@@ -1381,7 +1587,8 @@ class Backend(object):
def load_elliptic_curve_public_numbers(self, numbers):
ec_cdata = self._ec_key_new_by_curve(numbers.curve)
ec_cdata = self._ec_key_set_public_key_affine_coordinates(
- ec_cdata, numbers.x, numbers.y)
+ ec_cdata, numbers.x, numbers.y
+ )
evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata)
return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey)
@@ -1419,8 +1626,9 @@ class Backend(object):
value = self._ffi.gc(value, self._lib.BN_clear_free)
with self._tmp_bn_ctx() as bn_ctx:
- res = self._lib.EC_POINT_mul(group, point, value, self._ffi.NULL,
- self._ffi.NULL, bn_ctx)
+ res = self._lib.EC_POINT_mul(
+ group, point, value, self._ffi.NULL, self._ffi.NULL, bn_ctx
+ )
self.openssl_assert(res == 1)
bn_x = self._lib.BN_CTX_get(bn_ctx)
@@ -1442,6 +1650,9 @@ class Backend(object):
def _ec_key_new_by_curve(self, curve):
curve_nid = self._elliptic_curve_to_nid(curve)
+ return self._ec_key_new_by_curve_nid(curve_nid)
+
+ def _ec_key_new_by_curve_nid(self, curve_nid):
ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid)
self.openssl_assert(ec_cdata != self._ffi.NULL)
return self._ffi.gc(ec_cdata, self._lib.EC_KEY_free)
@@ -1472,15 +1683,13 @@ class Backend(object):
ocsp_req = self._ffi.gc(ocsp_req, self._lib.OCSP_REQUEST_free)
cert, issuer, algorithm = builder._request
evp_md = self._evp_md_non_null_from_algorithm(algorithm)
- certid = self._lib.OCSP_cert_to_id(
- evp_md, cert._x509, issuer._x509
- )
+ certid = self._lib.OCSP_cert_to_id(evp_md, cert._x509, issuer._x509)
self.openssl_assert(certid != self._ffi.NULL)
onereq = self._lib.OCSP_request_add0_id(ocsp_req, certid)
self.openssl_assert(onereq != self._ffi.NULL)
self._create_x509_extensions(
extensions=builder._extensions,
- handlers=_OCSP_REQUEST_EXTENSION_ENCODE_HANDLERS,
+ handlers=self._ocsp_request_extension_encode_handlers,
x509_obj=ocsp_req,
add_func=self._lib.OCSP_REQUEST_add_ext,
gc=True,
@@ -1488,6 +1697,8 @@ class Backend(object):
return _OCSPRequest(self, ocsp_req)
def _create_ocsp_basic_response(self, builder, private_key, algorithm):
+ self._x509_check_signature_params(private_key, algorithm)
+
basic = self._lib.OCSP_BASICRESP_new()
self.openssl_assert(basic != self._ffi.NULL)
basic = self._ffi.gc(basic, self._lib.OCSP_BASICRESP_free)
@@ -1495,8 +1706,9 @@ class Backend(object):
builder._response._algorithm
)
certid = self._lib.OCSP_cert_to_id(
- evp_md, builder._response._cert._x509,
- builder._response._issuer._x509
+ evp_md,
+ builder._response._cert._x509,
+ builder._response._issuer._x509,
)
self.openssl_assert(certid != self._ffi.NULL)
certid = self._ffi.gc(certid, self._lib.OCSP_CERTID_free)
@@ -1528,11 +1740,11 @@ class Backend(object):
reason,
rev_time,
this_update,
- next_update
+ next_update,
)
self.openssl_assert(res != self._ffi.NULL)
# okay, now sign the basic structure
- evp_md = self._evp_md_non_null_from_algorithm(algorithm)
+ evp_md = self._evp_md_x509_null_if_eddsa(private_key, algorithm)
responder_cert, responder_encoding = builder._responder_id
flags = self._lib.OCSP_NOCERTS
if responder_encoding is ocsp.OCSPResponderEncoding.HASH:
@@ -1545,30 +1757,33 @@ class Backend(object):
self._create_x509_extensions(
extensions=builder._extensions,
- handlers=_OCSP_BASICRESP_EXTENSION_ENCODE_HANDLERS,
+ handlers=self._ocsp_basicresp_extension_encode_handlers,
x509_obj=basic,
add_func=self._lib.OCSP_BASICRESP_add_ext,
gc=True,
)
res = self._lib.OCSP_basic_sign(
- basic, responder_cert._x509, private_key._evp_pkey,
- evp_md, self._ffi.NULL, flags
+ basic,
+ responder_cert._x509,
+ private_key._evp_pkey,
+ evp_md,
+ self._ffi.NULL,
+ flags,
)
if res != 1:
- errors = self._consume_errors()
- self.openssl_assert(
- errors[0]._lib_reason_match(
- self._lib.ERR_LIB_X509,
- self._lib.X509_R_KEY_VALUES_MISMATCH
- )
+ errors = self._consume_errors_with_text()
+ raise ValueError(
+ "Error while signing. responder_cert must be signed "
+ "by private_key",
+ errors,
)
- raise ValueError("responder_cert must be signed by private_key")
return basic
- def create_ocsp_response(self, response_status, builder, private_key,
- algorithm):
+ def create_ocsp_response(
+ self, response_status, builder, private_key, algorithm
+ ):
if response_status is ocsp.OCSPResponseStatus.SUCCESSFUL:
basic = self._create_ocsp_basic_response(
builder, private_key, algorithm
@@ -1584,9 +1799,8 @@ class Backend(object):
return _OCSPResponse(self, ocsp_resp)
def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve):
- return (
- self.elliptic_curve_supported(curve) and
- isinstance(algorithm, ec.ECDH)
+ return self.elliptic_curve_supported(curve) and isinstance(
+ algorithm, ec.ECDH
)
def _ec_cdata_to_evp_pkey(self, ec_cdata):
@@ -1600,18 +1814,15 @@ class Backend(object):
Get the NID for a curve name.
"""
- curve_aliases = {
- "secp192r1": "prime192v1",
- "secp256r1": "prime256v1"
- }
+ curve_aliases = {"secp192r1": "prime192v1", "secp256r1": "prime256v1"}
curve_name = curve_aliases.get(curve.name, curve.name)
curve_nid = self._lib.OBJ_sn2nid(curve_name.encode())
if curve_nid == self._lib.NID_undef:
raise UnsupportedAlgorithm(
- "{0} is not a supported elliptic curve".format(curve.name),
- _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+ "{} is not a supported elliptic curve".format(curve.name),
+ _Reasons.UNSUPPORTED_ELLIPTIC_CURVE,
)
return curve_nid
@@ -1674,47 +1885,32 @@ class Backend(object):
return ctx
- def _private_key_bytes(self, encoding, format, encryption_algorithm,
- evp_pkey, cdata):
+ def _private_key_bytes(
+ self, encoding, format, encryption_algorithm, key, evp_pkey, cdata
+ ):
+ # validate argument types
+ if not isinstance(encoding, serialization.Encoding):
+ raise TypeError("encoding must be an item from the Encoding enum")
if not isinstance(format, serialization.PrivateFormat):
raise TypeError(
"format must be an item from the PrivateFormat enum"
)
-
- # X9.62 encoding is only valid for EC public keys
- if encoding is serialization.Encoding.X962:
- raise ValueError("X9.62 format is only valid for EC public keys")
-
- # Raw format and encoding are only valid for X25519, Ed25519, X448, and
- # Ed448 keys. We capture those cases before this method is called so if
- # we see those enum values here it means the caller has passed them to
- # a key that doesn't support raw type
- if format is serialization.PrivateFormat.Raw:
- raise ValueError("raw format is invalid with this key or encoding")
-
- if encoding is serialization.Encoding.Raw:
- raise ValueError("raw encoding is invalid with this key or format")
-
- if not isinstance(encryption_algorithm,
- serialization.KeySerializationEncryption):
+ if not isinstance(
+ encryption_algorithm, serialization.KeySerializationEncryption
+ ):
raise TypeError(
"Encryption algorithm must be a KeySerializationEncryption "
"instance"
)
+ # validate password
if isinstance(encryption_algorithm, serialization.NoEncryption):
password = b""
- passlen = 0
- evp_cipher = self._ffi.NULL
- elif isinstance(encryption_algorithm,
- serialization.BestAvailableEncryption):
- # This is a curated value that we will update over time.
- evp_cipher = self._lib.EVP_get_cipherbyname(
- b"aes-256-cbc"
- )
+ elif isinstance(
+ encryption_algorithm, serialization.BestAvailableEncryption
+ ):
password = encryption_algorithm.password
- passlen = len(password)
- if passlen > 1023:
+ if len(password) > 1023:
raise ValueError(
"Passwords longer than 1023 bytes are not supported by "
"this backend"
@@ -1722,183 +1918,156 @@ class Backend(object):
else:
raise ValueError("Unsupported encryption type")
- key_type = self._lib.EVP_PKEY_id(evp_pkey)
- if encoding is serialization.Encoding.PEM:
- if format is serialization.PrivateFormat.PKCS8:
+ # PKCS8 + PEM/DER
+ if format is serialization.PrivateFormat.PKCS8:
+ if encoding is serialization.Encoding.PEM:
write_bio = self._lib.PEM_write_bio_PKCS8PrivateKey
- key = evp_pkey
+ elif encoding is serialization.Encoding.DER:
+ write_bio = self._lib.i2d_PKCS8PrivateKey_bio
else:
- assert format is serialization.PrivateFormat.TraditionalOpenSSL
+ raise ValueError("Unsupported encoding for PKCS8")
+ return self._private_key_bytes_via_bio(
+ write_bio, evp_pkey, password
+ )
+
+ # TraditionalOpenSSL + PEM/DER
+ if format is serialization.PrivateFormat.TraditionalOpenSSL:
+ if self._fips_enabled and not isinstance(
+ encryption_algorithm, serialization.NoEncryption
+ ):
+ raise ValueError(
+ "Encrypted traditional OpenSSL format is not "
+ "supported in FIPS mode."
+ )
+ key_type = self._lib.EVP_PKEY_id(evp_pkey)
+
+ if encoding is serialization.Encoding.PEM:
if key_type == self._lib.EVP_PKEY_RSA:
write_bio = self._lib.PEM_write_bio_RSAPrivateKey
elif key_type == self._lib.EVP_PKEY_DSA:
write_bio = self._lib.PEM_write_bio_DSAPrivateKey
- else:
- assert key_type == self._lib.EVP_PKEY_EC
+ elif key_type == self._lib.EVP_PKEY_EC:
write_bio = self._lib.PEM_write_bio_ECPrivateKey
+ else:
+ raise ValueError(
+ "Unsupported key type for TraditionalOpenSSL"
+ )
+ return self._private_key_bytes_via_bio(
+ write_bio, cdata, password
+ )
- key = cdata
- elif encoding is serialization.Encoding.DER:
- if format is serialization.PrivateFormat.TraditionalOpenSSL:
- if not isinstance(
- encryption_algorithm, serialization.NoEncryption
- ):
+ if encoding is serialization.Encoding.DER:
+ if password:
raise ValueError(
"Encryption is not supported for DER encoded "
"traditional OpenSSL keys"
)
+ if key_type == self._lib.EVP_PKEY_RSA:
+ write_bio = self._lib.i2d_RSAPrivateKey_bio
+ elif key_type == self._lib.EVP_PKEY_EC:
+ write_bio = self._lib.i2d_ECPrivateKey_bio
+ elif key_type == self._lib.EVP_PKEY_DSA:
+ write_bio = self._lib.i2d_DSAPrivateKey_bio
+ else:
+ raise ValueError(
+ "Unsupported key type for TraditionalOpenSSL"
+ )
+ return self._bio_func_output(write_bio, cdata)
- return self._private_key_bytes_traditional_der(key_type, cdata)
- else:
- assert format is serialization.PrivateFormat.PKCS8
- write_bio = self._lib.i2d_PKCS8PrivateKey_bio
- key = evp_pkey
+ raise ValueError("Unsupported encoding for TraditionalOpenSSL")
+
+ # OpenSSH + PEM
+ if format is serialization.PrivateFormat.OpenSSH:
+ if encoding is serialization.Encoding.PEM:
+ return ssh.serialize_ssh_private_key(key, password)
+
+ raise ValueError(
+ "OpenSSH private key format can only be used"
+ " with PEM encoding"
+ )
+
+ # Anything that key-specific code was supposed to handle earlier,
+ # like Raw.
+ raise ValueError("format is invalid with this key")
+
+ def _private_key_bytes_via_bio(self, write_bio, evp_pkey, password):
+ if not password:
+ evp_cipher = self._ffi.NULL
else:
- raise TypeError("encoding must be Encoding.PEM or Encoding.DER")
+ # This is a curated value that we will update over time.
+ evp_cipher = self._lib.EVP_get_cipherbyname(b"aes-256-cbc")
- bio = self._create_mem_bio_gc()
- res = write_bio(
- bio,
- key,
+ return self._bio_func_output(
+ write_bio,
+ evp_pkey,
evp_cipher,
password,
- passlen,
+ len(password),
+ self._ffi.NULL,
self._ffi.NULL,
- self._ffi.NULL
)
- self.openssl_assert(res == 1)
- return self._read_mem_bio(bio)
-
- def _private_key_bytes_traditional_der(self, key_type, cdata):
- if key_type == self._lib.EVP_PKEY_RSA:
- write_bio = self._lib.i2d_RSAPrivateKey_bio
- elif key_type == self._lib.EVP_PKEY_EC:
- write_bio = self._lib.i2d_ECPrivateKey_bio
- else:
- self.openssl_assert(key_type == self._lib.EVP_PKEY_DSA)
- write_bio = self._lib.i2d_DSAPrivateKey_bio
+ def _bio_func_output(self, write_bio, *args):
bio = self._create_mem_bio_gc()
- res = write_bio(bio, cdata)
+ res = write_bio(bio, *args)
self.openssl_assert(res == 1)
return self._read_mem_bio(bio)
def _public_key_bytes(self, encoding, format, key, evp_pkey, cdata):
if not isinstance(encoding, serialization.Encoding):
raise TypeError("encoding must be an item from the Encoding enum")
+ if not isinstance(format, serialization.PublicFormat):
+ raise TypeError(
+ "format must be an item from the PublicFormat enum"
+ )
- # Compressed/UncompressedPoint are only valid for EC keys and those
- # cases are handled by the ECPublicKey public_bytes method before this
- # method is called
- if format in (serialization.PublicFormat.UncompressedPoint,
- serialization.PublicFormat.CompressedPoint):
- raise ValueError("Point formats are not valid for this key type")
-
- # Raw format and encoding are only valid for X25519, Ed25519, X448, and
- # Ed448 keys. We capture those cases before this method is called so if
- # we see those enum values here it means the caller has passed them to
- # a key that doesn't support raw type
- if format is serialization.PublicFormat.Raw:
- raise ValueError("raw format is invalid with this key or encoding")
-
- if encoding is serialization.Encoding.Raw:
- raise ValueError("raw encoding is invalid with this key or format")
-
- if (
- format is serialization.PublicFormat.OpenSSH or
- encoding is serialization.Encoding.OpenSSH
- ):
- if (
- format is not serialization.PublicFormat.OpenSSH or
- encoding is not serialization.Encoding.OpenSSH
- ):
- raise ValueError(
- "OpenSSH format must be used with OpenSSH encoding"
- )
- return self._openssh_public_key_bytes(key)
- elif format is serialization.PublicFormat.SubjectPublicKeyInfo:
+ # SubjectPublicKeyInfo + PEM/DER
+ if format is serialization.PublicFormat.SubjectPublicKeyInfo:
if encoding is serialization.Encoding.PEM:
write_bio = self._lib.PEM_write_bio_PUBKEY
- else:
- assert encoding is serialization.Encoding.DER
+ elif encoding is serialization.Encoding.DER:
write_bio = self._lib.i2d_PUBKEY_bio
+ else:
+ raise ValueError(
+ "SubjectPublicKeyInfo works only with PEM or DER encoding"
+ )
+ return self._bio_func_output(write_bio, evp_pkey)
- key = evp_pkey
- elif format is serialization.PublicFormat.PKCS1:
+ # PKCS1 + PEM/DER
+ if format is serialization.PublicFormat.PKCS1:
# Only RSA is supported here.
- assert self._lib.EVP_PKEY_id(evp_pkey) == self._lib.EVP_PKEY_RSA
+ key_type = self._lib.EVP_PKEY_id(evp_pkey)
+ if key_type != self._lib.EVP_PKEY_RSA:
+ raise ValueError("PKCS1 format is supported only for RSA keys")
+
if encoding is serialization.Encoding.PEM:
write_bio = self._lib.PEM_write_bio_RSAPublicKey
- else:
- assert encoding is serialization.Encoding.DER
+ elif encoding is serialization.Encoding.DER:
write_bio = self._lib.i2d_RSAPublicKey_bio
+ else:
+ raise ValueError("PKCS1 works only with PEM or DER encoding")
+ return self._bio_func_output(write_bio, cdata)
- key = cdata
- else:
- raise TypeError(
- "format must be an item from the PublicFormat enum"
- )
-
- bio = self._create_mem_bio_gc()
- res = write_bio(bio, key)
- self.openssl_assert(res == 1)
- return self._read_mem_bio(bio)
+ # OpenSSH + OpenSSH
+ if format is serialization.PublicFormat.OpenSSH:
+ if encoding is serialization.Encoding.OpenSSH:
+ return ssh.serialize_ssh_public_key(key)
- def _openssh_public_key_bytes(self, key):
- if isinstance(key, rsa.RSAPublicKey):
- public_numbers = key.public_numbers()
- return b"ssh-rsa " + base64.b64encode(
- ssh._ssh_write_string(b"ssh-rsa") +
- ssh._ssh_write_mpint(public_numbers.e) +
- ssh._ssh_write_mpint(public_numbers.n)
- )
- elif isinstance(key, dsa.DSAPublicKey):
- public_numbers = key.public_numbers()
- parameter_numbers = public_numbers.parameter_numbers
- return b"ssh-dss " + base64.b64encode(
- ssh._ssh_write_string(b"ssh-dss") +
- ssh._ssh_write_mpint(parameter_numbers.p) +
- ssh._ssh_write_mpint(parameter_numbers.q) +
- ssh._ssh_write_mpint(parameter_numbers.g) +
- ssh._ssh_write_mpint(public_numbers.y)
+ raise ValueError(
+ "OpenSSH format must be used with OpenSSH encoding"
)
- else:
- assert isinstance(key, ec.EllipticCurvePublicKey)
- public_numbers = key.public_numbers()
- try:
- curve_name = {
- ec.SECP256R1: b"nistp256",
- ec.SECP384R1: b"nistp384",
- ec.SECP521R1: b"nistp521",
- }[type(public_numbers.curve)]
- except KeyError:
- raise ValueError(
- "Only SECP256R1, SECP384R1, and SECP521R1 curves are "
- "supported by the SSH public key format"
- )
- point = key.public_bytes(
- serialization.Encoding.X962,
- serialization.PublicFormat.UncompressedPoint
- )
- return b"ecdsa-sha2-" + curve_name + b" " + base64.b64encode(
- ssh._ssh_write_string(b"ecdsa-sha2-" + curve_name) +
- ssh._ssh_write_string(curve_name) +
- ssh._ssh_write_string(point)
- )
+ # Anything that key-specific code was supposed to handle earlier,
+ # like Raw, CompressedPoint, UncompressedPoint
+ raise ValueError("format is invalid with this key")
def _parameter_bytes(self, encoding, format, cdata):
if encoding is serialization.Encoding.OpenSSH:
- raise TypeError(
- "OpenSSH encoding is not supported"
- )
+ raise TypeError("OpenSSH encoding is not supported")
# Only DH is supported here currently.
q = self._ffi.new("BIGNUM **")
- self._lib.DH_get0_pqg(cdata,
- self._ffi.NULL,
- q,
- self._ffi.NULL)
+ self._lib.DH_get0_pqg(cdata, self._ffi.NULL, q, self._ffi.NULL)
if encoding is serialization.Encoding.PEM:
if q[0] != self._ffi.NULL:
write_bio = self._lib.PEM_write_bio_DHxparams
@@ -1918,8 +2087,12 @@ class Backend(object):
return self._read_mem_bio(bio)
def generate_dh_parameters(self, generator, key_size):
- if key_size < 512:
- raise ValueError("DH key_size must be at least 512 bits")
+ if key_size < dh._MIN_MODULUS_SIZE:
+ raise ValueError(
+ "DH key_size must be at least {} bits".format(
+ dh._MIN_MODULUS_SIZE
+ )
+ )
if generator not in (2, 5):
raise ValueError("DH generator must be 2 or 5")
@@ -1929,10 +2102,7 @@ class Backend(object):
dh_param_cdata = self._ffi.gc(dh_param_cdata, self._lib.DH_free)
res = self._lib.DH_generate_parameters_ex(
- dh_param_cdata,
- key_size,
- generator,
- self._ffi.NULL
+ dh_param_cdata, key_size, generator, self._ffi.NULL
)
self.openssl_assert(res == 1)
@@ -1956,7 +2126,8 @@ class Backend(object):
def generate_dh_private_key_and_parameters(self, generator, key_size):
return self.generate_dh_private_key(
- self.generate_dh_parameters(generator, key_size))
+ self.generate_dh_parameters(generator, key_size)
+ )
def load_dh_private_numbers(self, numbers):
parameter_numbers = numbers.public_numbers.parameter_numbers
@@ -1995,12 +2166,10 @@ class Backend(object):
# the key to the attacker in exchange for having the full key space
# available. See: https://crypto.stackexchange.com/questions/12961
if codes[0] != 0 and not (
- parameter_numbers.g == 2 and
- codes[0] ^ self._lib.DH_NOT_SUITABLE_GENERATOR == 0
+ parameter_numbers.g == 2
+ and codes[0] ^ self._lib.DH_NOT_SUITABLE_GENERATOR == 0
):
- raise ValueError(
- "DH private numbers did not pass safety checks."
- )
+ raise ValueError("DH private numbers did not pass safety checks.")
evp_pkey = self._dh_cdata_to_evp_pkey(dh_cdata)
@@ -2095,11 +2264,11 @@ class Backend(object):
evp_pkey = self._create_evp_pkey_gc()
res = self._lib.EVP_PKEY_set_type(evp_pkey, self._lib.NID_X25519)
- backend.openssl_assert(res == 1)
+ self.openssl_assert(res == 1)
res = self._lib.EVP_PKEY_set1_tls_encodedpoint(
evp_pkey, data, len(data)
)
- backend.openssl_assert(res == 1)
+ self.openssl_assert(res == 1)
return _X25519PublicKey(self, evp_pkey)
def x25519_load_private_bytes(self, data):
@@ -2127,7 +2296,7 @@ class Backend(object):
ba[0:16] = pkcs8_prefix
ba[16:] = data
bio = self._bytes_to_bio(ba)
- evp_pkey = backend._lib.d2i_PrivateKey_bio(bio.bio, self._ffi.NULL)
+ evp_pkey = self._lib.d2i_PrivateKey_bio(bio.bio, self._ffi.NULL)
self.openssl_assert(evp_pkey != self._ffi.NULL)
evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
@@ -2154,7 +2323,9 @@ class Backend(object):
return _X25519PrivateKey(self, evp_pkey)
def x25519_supported(self):
- return self._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
+ if self._fips_enabled:
+ return False
+ return not self._lib.CRYPTOGRAPHY_IS_LIBRESSL
def x448_load_public_bytes(self, data):
if len(data) != 56:
@@ -2184,44 +2355,115 @@ class Backend(object):
return _X448PrivateKey(self, evp_pkey)
def x448_supported(self):
+ if self._fips_enabled:
+ return False
return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111
+ def ed25519_supported(self):
+ if self._fips_enabled:
+ return False
+ return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B
+
+ def ed25519_load_public_bytes(self, data):
+ utils._check_bytes("data", data)
+
+ if len(data) != ed25519._ED25519_KEY_SIZE:
+ raise ValueError("An Ed25519 public key is 32 bytes long")
+
+ evp_pkey = self._lib.EVP_PKEY_new_raw_public_key(
+ self._lib.NID_ED25519, self._ffi.NULL, data, len(data)
+ )
+ self.openssl_assert(evp_pkey != self._ffi.NULL)
+ evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
+
+ return _Ed25519PublicKey(self, evp_pkey)
+
+ def ed25519_load_private_bytes(self, data):
+ if len(data) != ed25519._ED25519_KEY_SIZE:
+ raise ValueError("An Ed25519 private key is 32 bytes long")
+
+ utils._check_byteslike("data", data)
+ data_ptr = self._ffi.from_buffer(data)
+ evp_pkey = self._lib.EVP_PKEY_new_raw_private_key(
+ self._lib.NID_ED25519, self._ffi.NULL, data_ptr, len(data)
+ )
+ self.openssl_assert(evp_pkey != self._ffi.NULL)
+ evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
+
+ return _Ed25519PrivateKey(self, evp_pkey)
+
+ def ed25519_generate_key(self):
+ evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_ED25519)
+ return _Ed25519PrivateKey(self, evp_pkey)
+
+ def ed448_supported(self):
+ if self._fips_enabled:
+ return False
+ return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B
+
+ def ed448_load_public_bytes(self, data):
+ utils._check_bytes("data", data)
+ if len(data) != _ED448_KEY_SIZE:
+ raise ValueError("An Ed448 public key is 57 bytes long")
+
+ evp_pkey = self._lib.EVP_PKEY_new_raw_public_key(
+ self._lib.NID_ED448, self._ffi.NULL, data, len(data)
+ )
+ self.openssl_assert(evp_pkey != self._ffi.NULL)
+ evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
+
+ return _Ed448PublicKey(self, evp_pkey)
+
+ def ed448_load_private_bytes(self, data):
+ utils._check_byteslike("data", data)
+ if len(data) != _ED448_KEY_SIZE:
+ raise ValueError("An Ed448 private key is 57 bytes long")
+
+ data_ptr = self._ffi.from_buffer(data)
+ evp_pkey = self._lib.EVP_PKEY_new_raw_private_key(
+ self._lib.NID_ED448, self._ffi.NULL, data_ptr, len(data)
+ )
+ self.openssl_assert(evp_pkey != self._ffi.NULL)
+ evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
+
+ return _Ed448PrivateKey(self, evp_pkey)
+
+ def ed448_generate_key(self):
+ evp_pkey = self._evp_pkey_keygen_gc(self._lib.NID_ED448)
+ return _Ed448PrivateKey(self, evp_pkey)
+
def derive_scrypt(self, key_material, salt, length, n, r, p):
buf = self._ffi.new("unsigned char[]", length)
key_material_ptr = self._ffi.from_buffer(key_material)
res = self._lib.EVP_PBE_scrypt(
- key_material_ptr, len(key_material), salt, len(salt), n, r, p,
- scrypt._MEM_LIMIT, buf, length
+ key_material_ptr,
+ len(key_material),
+ salt,
+ len(salt),
+ n,
+ r,
+ p,
+ scrypt._MEM_LIMIT,
+ buf,
+ length,
)
if res != 1:
- errors = self._consume_errors()
- if not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111:
- # This error is only added to the stack in 1.1.1+
- self.openssl_assert(
- errors[0]._lib_reason_match(
- self._lib.ERR_LIB_EVP,
- self._lib.ERR_R_MALLOC_FAILURE
- ) or
- errors[0]._lib_reason_match(
- self._lib.ERR_LIB_EVP,
- self._lib.EVP_R_MEMORY_LIMIT_EXCEEDED
- )
- )
-
+ errors = self._consume_errors_with_text()
# memory required formula explained here:
# https://blog.filippo.io/the-scrypt-parameters/
- min_memory = 128 * n * r // (1024**2)
+ min_memory = 128 * n * r // (1024 ** 2)
raise MemoryError(
"Not enough memory to derive key. These parameters require"
- " {} MB of memory.".format(min_memory)
+ " {} MB of memory.".format(min_memory),
+ errors,
)
return self._ffi.buffer(buf)[:]
def aead_cipher_supported(self, cipher):
cipher_name = aead._aead_cipher_name(cipher)
- return (
- self._lib.EVP_get_cipherbyname(cipher_name) != self._ffi.NULL
- )
+ if self._fips_enabled and cipher_name not in self._fips_aead:
+ return False
+ return self._lib.EVP_get_cipherbyname(cipher_name) != self._ffi.NULL
@contextlib.contextmanager
def _zeroed_bytearray(self, length):
@@ -2306,12 +2548,216 @@ class Backend(object):
num = self._lib.sk_X509_num(sk_x509_ptr[0])
for i in range(num):
x509 = self._lib.sk_X509_value(sk_x509, i)
- x509 = self._ffi.gc(x509, self._lib.X509_free)
self.openssl_assert(x509 != self._ffi.NULL)
+ x509 = self._ffi.gc(x509, self._lib.X509_free)
additional_certificates.append(_Certificate(self, x509))
return (key, cert, additional_certificates)
+ def serialize_key_and_certificates_to_pkcs12(
+ self, name, key, cert, cas, encryption_algorithm
+ ):
+ password = None
+ if name is not None:
+ utils._check_bytes("name", name)
+
+ if isinstance(encryption_algorithm, serialization.NoEncryption):
+ nid_cert = -1
+ nid_key = -1
+ pkcs12_iter = 0
+ mac_iter = 0
+ elif isinstance(
+ encryption_algorithm, serialization.BestAvailableEncryption
+ ):
+ # PKCS12 encryption is hopeless trash and can never be fixed.
+ # This is the least terrible option.
+ nid_cert = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC
+ nid_key = self._lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC
+ # At least we can set this higher than OpenSSL's default
+ pkcs12_iter = 20000
+ # mac_iter chosen for compatibility reasons, see:
+ # https://www.openssl.org/docs/man1.1.1/man3/PKCS12_create.html
+ # Did we mention how lousy PKCS12 encryption is?
+ mac_iter = 1
+ password = encryption_algorithm.password
+ else:
+ raise ValueError("Unsupported key encryption type")
+
+ if cas is None or len(cas) == 0:
+ sk_x509 = self._ffi.NULL
+ else:
+ sk_x509 = self._lib.sk_X509_new_null()
+ sk_x509 = self._ffi.gc(sk_x509, self._lib.sk_X509_free)
+
+ # reverse the list when building the stack so that they're encoded
+ # in the order they were originally provided. it is a mystery
+ for ca in reversed(cas):
+ res = self._lib.sk_X509_push(sk_x509, ca._x509)
+ backend.openssl_assert(res >= 1)
+
+ with self._zeroed_null_terminated_buf(password) as password_buf:
+ with self._zeroed_null_terminated_buf(name) as name_buf:
+ p12 = self._lib.PKCS12_create(
+ password_buf,
+ name_buf,
+ key._evp_pkey if key else self._ffi.NULL,
+ cert._x509 if cert else self._ffi.NULL,
+ sk_x509,
+ nid_key,
+ nid_cert,
+ pkcs12_iter,
+ mac_iter,
+ 0,
+ )
+
+ self.openssl_assert(p12 != self._ffi.NULL)
+ p12 = self._ffi.gc(p12, self._lib.PKCS12_free)
+
+ bio = self._create_mem_bio_gc()
+ res = self._lib.i2d_PKCS12_bio(bio, p12)
+ self.openssl_assert(res > 0)
+ return self._read_mem_bio(bio)
+
+ def poly1305_supported(self):
+ if self._fips_enabled:
+ return False
+ return self._lib.Cryptography_HAS_POLY1305 == 1
+
+ def create_poly1305_ctx(self, key):
+ utils._check_byteslike("key", key)
+ if len(key) != _POLY1305_KEY_SIZE:
+ raise ValueError("A poly1305 key is 32 bytes long")
+
+ return _Poly1305Context(self, key)
+
+ def load_pem_pkcs7_certificates(self, data):
+ utils._check_bytes("data", data)
+ bio = self._bytes_to_bio(data)
+ p7 = self._lib.PEM_read_bio_PKCS7(
+ bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL
+ )
+ if p7 == self._ffi.NULL:
+ self._consume_errors()
+ raise ValueError("Unable to parse PKCS7 data")
+
+ p7 = self._ffi.gc(p7, self._lib.PKCS7_free)
+ return self._load_pkcs7_certificates(p7)
+
+ def load_der_pkcs7_certificates(self, data):
+ utils._check_bytes("data", data)
+ bio = self._bytes_to_bio(data)
+ p7 = self._lib.d2i_PKCS7_bio(bio.bio, self._ffi.NULL)
+ if p7 == self._ffi.NULL:
+ self._consume_errors()
+ raise ValueError("Unable to parse PKCS7 data")
+
+ p7 = self._ffi.gc(p7, self._lib.PKCS7_free)
+ return self._load_pkcs7_certificates(p7)
+
+ def _load_pkcs7_certificates(self, p7):
+ nid = self._lib.OBJ_obj2nid(p7.type)
+ self.openssl_assert(nid != self._lib.NID_undef)
+ if nid != self._lib.NID_pkcs7_signed:
+ raise UnsupportedAlgorithm(
+ "Only basic signed structures are currently supported. NID"
+ " for this data was {}".format(nid),
+ _Reasons.UNSUPPORTED_SERIALIZATION,
+ )
+
+ sk_x509 = p7.d.sign.cert
+ num = self._lib.sk_X509_num(sk_x509)
+ certs = []
+ for i in range(num):
+ x509 = self._lib.sk_X509_value(sk_x509, i)
+ self.openssl_assert(x509 != self._ffi.NULL)
+ res = self._lib.X509_up_ref(x509)
+ # When OpenSSL is less than 1.1.0 up_ref returns the current
+ # refcount. On 1.1.0+ it returns 1 for success.
+ self.openssl_assert(res >= 1)
+ x509 = self._ffi.gc(x509, self._lib.X509_free)
+ certs.append(_Certificate(self, x509))
+
+ return certs
+
+ def pkcs7_sign(self, builder, encoding, options):
+ bio = self._bytes_to_bio(builder._data)
+ init_flags = self._lib.PKCS7_PARTIAL
+ final_flags = 0
+
+ if len(builder._additional_certs) == 0:
+ certs = self._ffi.NULL
+ else:
+ certs = self._lib.sk_X509_new_null()
+ certs = self._ffi.gc(certs, self._lib.sk_X509_free)
+ for cert in builder._additional_certs:
+ res = self._lib.sk_X509_push(certs, cert._x509)
+ self.openssl_assert(res >= 1)
+
+ if pkcs7.PKCS7Options.DetachedSignature in options:
+ # Don't embed the data in the PKCS7 structure
+ init_flags |= self._lib.PKCS7_DETACHED
+ final_flags |= self._lib.PKCS7_DETACHED
+
+ # This just inits a structure for us. However, there
+ # are flags we need to set, joy.
+ p7 = self._lib.PKCS7_sign(
+ self._ffi.NULL,
+ self._ffi.NULL,
+ certs,
+ self._ffi.NULL,
+ init_flags,
+ )
+ self.openssl_assert(p7 != self._ffi.NULL)
+ p7 = self._ffi.gc(p7, self._lib.PKCS7_free)
+ signer_flags = 0
+ # These flags are configurable on a per-signature basis
+ # but we've deliberately chosen to make the API only allow
+ # setting it across all signatures for now.
+ if pkcs7.PKCS7Options.NoCapabilities in options:
+ signer_flags |= self._lib.PKCS7_NOSMIMECAP
+ elif pkcs7.PKCS7Options.NoAttributes in options:
+ signer_flags |= self._lib.PKCS7_NOATTR
+
+ if pkcs7.PKCS7Options.NoCerts in options:
+ signer_flags |= self._lib.PKCS7_NOCERTS
+
+ for certificate, private_key, hash_algorithm in builder._signers:
+ md = self._evp_md_non_null_from_algorithm(hash_algorithm)
+ p7signerinfo = self._lib.PKCS7_sign_add_signer(
+ p7, certificate._x509, private_key._evp_pkey, md, signer_flags
+ )
+ self.openssl_assert(p7signerinfo != self._ffi.NULL)
+
+ for option in options:
+ # DetachedSignature, NoCapabilities, and NoAttributes are already
+ # handled so we just need to check these last two options.
+ if option is pkcs7.PKCS7Options.Text:
+ final_flags |= self._lib.PKCS7_TEXT
+ elif option is pkcs7.PKCS7Options.Binary:
+ final_flags |= self._lib.PKCS7_BINARY
+
+ bio_out = self._create_mem_bio_gc()
+ if encoding is serialization.Encoding.SMIME:
+ # This finalizes the structure
+ res = self._lib.SMIME_write_PKCS7(
+ bio_out, p7, bio.bio, final_flags
+ )
+ elif encoding is serialization.Encoding.PEM:
+ res = self._lib.PKCS7_final(p7, bio.bio, final_flags)
+ self.openssl_assert(res == 1)
+ res = self._lib.PEM_write_bio_PKCS7_stream(
+ bio_out, p7, bio.bio, final_flags
+ )
+ else:
+ assert encoding is serialization.Encoding.DER
+ # We need to call finalize here becauase i2d_PKCS7_bio does not
+ # finalize.
+ res = self._lib.PKCS7_final(p7, bio.bio, final_flags)
+ self.openssl_assert(res == 1)
+ res = self._lib.i2d_PKCS7_bio(bio_out, p7)
+ self.openssl_assert(res == 1)
+ return self._read_mem_bio(bio_out)
+
class GetCipherByName(object):
def __init__(self, fmt):
@@ -2323,7 +2769,7 @@ class GetCipherByName(object):
def _get_xts_cipher(backend, cipher, mode):
- cipher_name = "aes-{0}-xts".format(cipher.key_size // 2)
+ cipher_name = "aes-{}-xts".format(cipher.key_size // 2)
return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii"))
diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py
index 66ac5fd69..ad5dad3f7 100644
--- a/src/cryptography/hazmat/backends/openssl/ciphers.py
+++ b/src/cryptography/hazmat/backends/openssl/ciphers.py
@@ -17,6 +17,7 @@ from cryptography.hazmat.primitives.ciphers import modes
class _CipherContext(object):
_ENCRYPT = 1
_DECRYPT = 0
+ _MAX_CHUNK_SIZE = 2 ** 30 - 1
def __init__(self, backend, cipher, mode, operation):
self._backend = backend
@@ -40,10 +41,11 @@ class _CipherContext(object):
adapter = registry[type(cipher), type(mode)]
except KeyError:
raise UnsupportedAlgorithm(
- "cipher {0} in {1} mode is not supported "
+ "cipher {} in {} mode is not supported "
"by this backend.".format(
- cipher.name, mode.name if mode else mode),
- _Reasons.UNSUPPORTED_CIPHER
+ cipher.name, mode.name if mode else mode
+ ),
+ _Reasons.UNSUPPORTED_CIPHER,
)
evp_cipher = adapter(self._backend, cipher, mode)
@@ -53,7 +55,7 @@ class _CipherContext(object):
msg += "in {0.name} mode ".format(mode)
msg += (
"is not supported by this backend (Your version of OpenSSL "
- "may be too old. Current version: {0}.)"
+ "may be too old. Current version: {}.)"
).format(self._backend.openssl_version_text())
raise UnsupportedAlgorithm(msg, _Reasons.UNSUPPORTED_CIPHER)
@@ -70,11 +72,14 @@ class _CipherContext(object):
else:
iv_nonce = self._backend._ffi.NULL
# begin init with cipher and operation type
- res = self._backend._lib.EVP_CipherInit_ex(ctx, evp_cipher,
- self._backend._ffi.NULL,
- self._backend._ffi.NULL,
- self._backend._ffi.NULL,
- operation)
+ res = self._backend._lib.EVP_CipherInit_ex(
+ ctx,
+ evp_cipher,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ operation,
+ )
self._backend.openssl_assert(res != 0)
# set the key length to handle variable key ciphers
res = self._backend._lib.EVP_CIPHER_CTX_set_key_length(
@@ -83,26 +88,21 @@ class _CipherContext(object):
self._backend.openssl_assert(res != 0)
if isinstance(mode, modes.GCM):
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
- ctx, self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN,
- len(iv_nonce), self._backend._ffi.NULL
+ ctx,
+ self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN,
+ len(iv_nonce),
+ self._backend._ffi.NULL,
)
self._backend.openssl_assert(res != 0)
if mode.tag is not None:
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
- ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG,
- len(mode.tag), mode.tag
+ ctx,
+ self._backend._lib.EVP_CTRL_AEAD_SET_TAG,
+ len(mode.tag),
+ mode.tag,
)
self._backend.openssl_assert(res != 0)
self._tag = mode.tag
- elif (
- self._operation == self._DECRYPT and
- self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
- not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
- ):
- raise NotImplementedError(
- "delayed passing of GCM tag requires OpenSSL >= 1.0.2."
- " To use this feature please update OpenSSL"
- )
# pass key/iv
res = self._backend._lib.EVP_CipherInit_ex(
@@ -111,7 +111,7 @@ class _CipherContext(object):
self._backend._ffi.NULL,
self._backend._ffi.from_buffer(cipher.key),
iv_nonce,
- operation
+ operation,
)
self._backend.openssl_assert(res != 0)
# We purposely disable padding here as it's handled higher up in the
@@ -125,36 +125,38 @@ class _CipherContext(object):
return bytes(buf[:n])
def update_into(self, data, buf):
- if len(buf) < (len(data) + self._block_size_bytes - 1):
+ total_data_len = len(data)
+ if len(buf) < (total_data_len + self._block_size_bytes - 1):
raise ValueError(
- "buffer must be at least {0} bytes for this "
+ "buffer must be at least {} bytes for this "
"payload".format(len(data) + self._block_size_bytes - 1)
)
- buf = self._backend._ffi.cast(
- "unsigned char *", self._backend._ffi.from_buffer(buf)
- )
+ data_processed = 0
+ total_out = 0
outlen = self._backend._ffi.new("int *")
- res = self._backend._lib.EVP_CipherUpdate(
- self._ctx, buf, outlen,
- self._backend._ffi.from_buffer(data), len(data)
- )
- self._backend.openssl_assert(res != 0)
- return outlen[0]
+ baseoutbuf = self._backend._ffi.from_buffer(buf)
+ baseinbuf = self._backend._ffi.from_buffer(data)
- def finalize(self):
- # OpenSSL 1.0.1 on Ubuntu 12.04 (and possibly other distributions)
- # appears to have a bug where you must make at least one call to update
- # even if you are only using authenticate_additional_data or the
- # GCM tag will be wrong. An (empty) call to update resolves this
- # and is harmless for all other versions of OpenSSL.
- if isinstance(self._mode, modes.GCM):
- self.update(b"")
+ while data_processed != total_data_len:
+ outbuf = baseoutbuf + total_out
+ inbuf = baseinbuf + data_processed
+ inlen = min(self._MAX_CHUNK_SIZE, total_data_len - data_processed)
+ res = self._backend._lib.EVP_CipherUpdate(
+ self._ctx, outbuf, outlen, inbuf, inlen
+ )
+ self._backend.openssl_assert(res != 0)
+ data_processed += inlen
+ total_out += outlen[0]
+
+ return total_out
+
+ def finalize(self):
if (
- self._operation == self._DECRYPT and
- isinstance(self._mode, modes.ModeWithAuthenticationTag) and
- self.tag is None
+ self._operation == self._DECRYPT
+ and isinstance(self._mode, modes.ModeWithAuthenticationTag)
+ and self.tag is None
):
raise ValueError(
"Authentication tag must be provided when decrypting."
@@ -172,47 +174,44 @@ class _CipherContext(object):
self._backend.openssl_assert(
errors[0]._lib_reason_match(
self._backend._lib.ERR_LIB_EVP,
- self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
- )
+ self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,
+ ),
+ errors=errors,
)
raise ValueError(
"The length of the provided data is not a multiple of "
"the block length."
)
- if (isinstance(self._mode, modes.GCM) and
- self._operation == self._ENCRYPT):
+ if (
+ isinstance(self._mode, modes.GCM)
+ and self._operation == self._ENCRYPT
+ ):
tag_buf = self._backend._ffi.new(
"unsigned char[]", self._block_size_bytes
)
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
- self._ctx, self._backend._lib.EVP_CTRL_AEAD_GET_TAG,
- self._block_size_bytes, tag_buf
+ self._ctx,
+ self._backend._lib.EVP_CTRL_AEAD_GET_TAG,
+ self._block_size_bytes,
+ tag_buf,
)
self._backend.openssl_assert(res != 0)
self._tag = self._backend._ffi.buffer(tag_buf)[:]
res = self._backend._lib.EVP_CIPHER_CTX_cleanup(self._ctx)
self._backend.openssl_assert(res == 1)
- return self._backend._ffi.buffer(buf)[:outlen[0]]
+ return self._backend._ffi.buffer(buf)[: outlen[0]]
def finalize_with_tag(self, tag):
- if (
- self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
- not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
- ):
- raise NotImplementedError(
- "finalize_with_tag requires OpenSSL >= 1.0.2. To use this "
- "method please update OpenSSL"
- )
if len(tag) < self._mode._min_tag_length:
raise ValueError(
- "Authentication tag must be {0} bytes or longer.".format(
- self._mode._min_tag_length)
+ "Authentication tag must be {} bytes or longer.".format(
+ self._mode._min_tag_length
+ )
)
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
- self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG,
- len(tag), tag
+ self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag
)
self._backend.openssl_assert(res != 0)
self._tag = tag
@@ -221,8 +220,11 @@ class _CipherContext(object):
def authenticate_additional_data(self, data):
outlen = self._backend._ffi.new("int *")
res = self._backend._lib.EVP_CipherUpdate(
- self._ctx, self._backend._ffi.NULL, outlen,
- self._backend._ffi.from_buffer(data), len(data)
+ self._ctx,
+ self._backend._ffi.NULL,
+ outlen,
+ self._backend._ffi.from_buffer(data),
+ len(data),
)
self._backend.openssl_assert(res != 0)
diff --git a/src/cryptography/hazmat/backends/openssl/cmac.py b/src/cryptography/hazmat/backends/openssl/cmac.py
index bc88f3364..195fc230f 100644
--- a/src/cryptography/hazmat/backends/openssl/cmac.py
+++ b/src/cryptography/hazmat/backends/openssl/cmac.py
@@ -7,18 +7,21 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import (
- InvalidSignature, UnsupportedAlgorithm, _Reasons
+ InvalidSignature,
+ UnsupportedAlgorithm,
+ _Reasons,
)
-from cryptography.hazmat.primitives import constant_time, mac
+from cryptography.hazmat.primitives import constant_time
from cryptography.hazmat.primitives.ciphers.modes import CBC
-@utils.register_interface(mac.MACContext)
class _CMACContext(object):
def __init__(self, backend, algorithm, ctx=None):
if not backend.cmac_algorithm_supported(algorithm):
- raise UnsupportedAlgorithm("This backend does not support CMAC.",
- _Reasons.UNSUPPORTED_CIPHER)
+ raise UnsupportedAlgorithm(
+ "This backend does not support CMAC.",
+ _Reasons.UNSUPPORTED_CIPHER,
+ )
self._backend = backend
self._key = algorithm.key
@@ -38,8 +41,11 @@ class _CMACContext(object):
key_ptr = self._backend._ffi.from_buffer(self._key)
res = self._backend._lib.CMAC_Init(
- ctx, key_ptr, len(self._key),
- evp_cipher, self._backend._ffi.NULL
+ ctx,
+ key_ptr,
+ len(self._key),
+ evp_cipher,
+ self._backend._ffi.NULL,
)
self._backend.openssl_assert(res == 1)
@@ -54,9 +60,7 @@ class _CMACContext(object):
def finalize(self):
buf = self._backend._ffi.new("unsigned char[]", self._output_length)
length = self._backend._ffi.new("size_t *", self._output_length)
- res = self._backend._lib.CMAC_Final(
- self._ctx, buf, length
- )
+ res = self._backend._lib.CMAC_Final(self._ctx, buf, length)
self._backend.openssl_assert(res == 1)
self._ctx = None
@@ -68,13 +72,9 @@ class _CMACContext(object):
copied_ctx = self._backend._ffi.gc(
copied_ctx, self._backend._lib.CMAC_CTX_free
)
- res = self._backend._lib.CMAC_CTX_copy(
- copied_ctx, self._ctx
- )
+ res = self._backend._lib.CMAC_CTX_copy(copied_ctx, self._ctx)
self._backend.openssl_assert(res == 1)
- return _CMACContext(
- self._backend, self._algorithm, ctx=copied_ctx
- )
+ return _CMACContext(self._backend, self._algorithm, ctx=copied_ctx)
def verify(self, signature):
digest = self.finalize()
diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py
index 007675d4e..cc9b8c0e3 100644
--- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py
@@ -7,23 +7,20 @@ from __future__ import absolute_import, division, print_function
import datetime
import ipaddress
-import asn1crypto.core
-
import six
from cryptography import x509
+from cryptography.hazmat._der import DERReader, INTEGER, NULL, SEQUENCE
from cryptography.x509.extensions import _TLS_FEATURE_TYPE_TO_ENUM
from cryptography.x509.name import _ASN1_TYPE_TO_ENUM
from cryptography.x509.oid import (
- CRLEntryExtensionOID, CertificatePoliciesOID, ExtensionOID,
+ CRLEntryExtensionOID,
+ CertificatePoliciesOID,
+ ExtensionOID,
OCSPExtensionOID,
)
-class _Integers(asn1crypto.core.SequenceOf):
- _child_spec = asn1crypto.core.Integer
-
-
def _obj2txt(backend, obj):
# Set to 80 on the recommendation of
# https://www.openssl.org/docs/crypto/OBJ_nid2ln.html#return_values
@@ -67,9 +64,9 @@ def _decode_x509_name(backend, x509_name):
for x in range(count):
entry = backend._lib.X509_NAME_get_entry(x509_name, x)
attribute = _decode_x509_name_entry(backend, entry)
- set_id = backend._lib.Cryptography_X509_NAME_ENTRY_set(entry)
+ set_id = backend._lib.X509_NAME_ENTRY_set(entry)
if set_id != prev_set_id:
- attributes.append(set([attribute]))
+ attributes.append({attribute})
else:
# is in the same RDN a previous entry
attributes[-1].add(attribute)
@@ -124,10 +121,10 @@ def _decode_general_name(backend, gn):
# netmask. To handle this we convert the netmask to integer, then
# find the first 0 bit, which will be the prefix. If another 1
# bit is present after that the netmask is invalid.
- base = ipaddress.ip_address(data[:data_len // 2])
- netmask = ipaddress.ip_address(data[data_len // 2:])
+ base = ipaddress.ip_address(data[: data_len // 2])
+ netmask = ipaddress.ip_address(data[data_len // 2 :])
bits = bin(int(netmask))[2:]
- prefix = bits.find('0')
+ prefix = bits.find("0")
# If no 0 bits are found it is a /32 or /128
if prefix == -1:
prefix = len(bits)
@@ -135,7 +132,7 @@ def _decode_general_name(backend, gn):
if "1" in bits[prefix:]:
raise ValueError("Invalid netmask")
- ip = ipaddress.ip_network(base.exploded + u"/{0}".format(prefix))
+ ip = ipaddress.ip_network(base.exploded + u"/{}".format(prefix))
else:
ip = ipaddress.ip_address(data)
@@ -160,10 +157,10 @@ def _decode_general_name(backend, gn):
else:
# x400Address or ediPartyName
raise x509.UnsupportedGeneralNameType(
- "{0} is not a supported type".format(
+ "{} is not a supported type".format(
x509._GENERAL_NAMES.get(gn.type, gn.type)
),
- gn.type
+ gn.type,
)
@@ -184,48 +181,57 @@ def _decode_delta_crl_indicator(backend, ext):
class _X509ExtensionParser(object):
- def __init__(self, ext_count, get_ext, handlers):
+ def __init__(self, backend, ext_count, get_ext, handlers):
self.ext_count = ext_count
self.get_ext = get_ext
self.handlers = handlers
+ self._backend = backend
- def parse(self, backend, x509_obj):
+ def parse(self, x509_obj):
extensions = []
seen_oids = set()
- for i in range(self.ext_count(backend, x509_obj)):
- ext = self.get_ext(backend, x509_obj, i)
- backend.openssl_assert(ext != backend._ffi.NULL)
- crit = backend._lib.X509_EXTENSION_get_critical(ext)
+ for i in range(self.ext_count(x509_obj)):
+ ext = self.get_ext(x509_obj, i)
+ self._backend.openssl_assert(ext != self._backend._ffi.NULL)
+ crit = self._backend._lib.X509_EXTENSION_get_critical(ext)
critical = crit == 1
oid = x509.ObjectIdentifier(
- _obj2txt(backend, backend._lib.X509_EXTENSION_get_object(ext))
+ _obj2txt(
+ self._backend,
+ self._backend._lib.X509_EXTENSION_get_object(ext),
+ )
)
if oid in seen_oids:
raise x509.DuplicateExtension(
- "Duplicate {0} extension found".format(oid), oid
+ "Duplicate {} extension found".format(oid), oid
)
# These OIDs are only supported in OpenSSL 1.1.0+ but we want
# to support them in all versions of OpenSSL so we decode them
# ourselves.
if oid == ExtensionOID.TLS_FEATURE:
- data = backend._lib.X509_EXTENSION_get_data(ext)
- parsed = _Integers.load(_asn1_string_to_bytes(backend, data))
+ # The extension contents are a SEQUENCE OF INTEGERs.
+ data = self._backend._lib.X509_EXTENSION_get_data(ext)
+ data_bytes = _asn1_string_to_bytes(self._backend, data)
+ features = DERReader(data_bytes).read_single_element(SEQUENCE)
+ parsed = []
+ while not features.is_empty():
+ parsed.append(features.read_element(INTEGER).as_integer())
+ # Map the features to their enum value.
value = x509.TLSFeature(
- [_TLS_FEATURE_TYPE_TO_ENUM[x.native] for x in parsed]
+ [_TLS_FEATURE_TYPE_TO_ENUM[x] for x in parsed]
)
extensions.append(x509.Extension(oid, critical, value))
seen_oids.add(oid)
continue
elif oid == ExtensionOID.PRECERT_POISON:
- data = backend._lib.X509_EXTENSION_get_data(ext)
- parsed = asn1crypto.core.Null.load(
- _asn1_string_to_bytes(backend, data)
+ data = self._backend._lib.X509_EXTENSION_get_data(ext)
+ # The contents of the extension must be an ASN.1 NULL.
+ reader = DERReader(_asn1_string_to_bytes(self._backend, data))
+ reader.read_single_element(NULL).check_empty()
+ extensions.append(
+ x509.Extension(oid, critical, x509.PrecertPoison())
)
- assert parsed == asn1crypto.core.Null()
- extensions.append(x509.Extension(
- oid, critical, x509.PrecertPoison()
- ))
seen_oids.add(oid)
continue
@@ -233,23 +239,21 @@ class _X509ExtensionParser(object):
handler = self.handlers[oid]
except KeyError:
# Dump the DER payload into an UnrecognizedExtension object
- data = backend._lib.X509_EXTENSION_get_data(ext)
- backend.openssl_assert(data != backend._ffi.NULL)
- der = backend._ffi.buffer(data.data, data.length)[:]
+ data = self._backend._lib.X509_EXTENSION_get_data(ext)
+ self._backend.openssl_assert(data != self._backend._ffi.NULL)
+ der = self._backend._ffi.buffer(data.data, data.length)[:]
unrecognized = x509.UnrecognizedExtension(oid, der)
- extensions.append(
- x509.Extension(oid, critical, unrecognized)
- )
+ extensions.append(x509.Extension(oid, critical, unrecognized))
else:
- ext_data = backend._lib.X509V3_EXT_d2i(ext)
- if ext_data == backend._ffi.NULL:
- backend._consume_errors()
+ ext_data = self._backend._lib.X509V3_EXT_d2i(ext)
+ if ext_data == self._backend._ffi.NULL:
+ self._backend._consume_errors()
raise ValueError(
- "The {0} extension is invalid and can't be "
+ "The {} extension is invalid and can't be "
"parsed".format(oid)
)
- value = handler(backend, ext_data)
+ value = handler(self._backend, ext_data)
extensions.append(x509.Extension(oid, critical, value))
seen_oids.add(oid)
@@ -271,16 +275,12 @@ def _decode_certificate_policies(backend, cp):
qnum = backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers)
qualifiers = []
for j in range(qnum):
- pqi = backend._lib.sk_POLICYQUALINFO_value(
- pi.qualifiers, j
- )
- pqualid = x509.ObjectIdentifier(
- _obj2txt(backend, pqi.pqualid)
- )
+ pqi = backend._lib.sk_POLICYQUALINFO_value(pi.qualifiers, j)
+ pqualid = x509.ObjectIdentifier(_obj2txt(backend, pqi.pqualid))
if pqualid == CertificatePoliciesOID.CPS_QUALIFIER:
cpsuri = backend._ffi.buffer(
pqi.d.cpsuri.data, pqi.d.cpsuri.length
- )[:].decode('ascii')
+ )[:].decode("ascii")
qualifiers.append(cpsuri)
else:
assert pqualid == CertificatePoliciesOID.CPS_USER_NOTICE
@@ -289,9 +289,7 @@ def _decode_certificate_policies(backend, cp):
)
qualifiers.append(user_notice)
- certificate_policies.append(
- x509.PolicyInformation(oid, qualifiers)
- )
+ certificate_policies.append(x509.PolicyInformation(oid, qualifiers))
return x509.CertificatePolicies(certificate_policies)
@@ -304,13 +302,9 @@ def _decode_user_notice(backend, un):
explicit_text = _asn1_string_to_utf8(backend, un.exptext)
if un.noticeref != backend._ffi.NULL:
- organization = _asn1_string_to_utf8(
- backend, un.noticeref.organization
- )
+ organization = _asn1_string_to_utf8(backend, un.noticeref.organization)
- num = backend._lib.sk_ASN1_INTEGER_num(
- un.noticeref.noticenos
- )
+ num = backend._lib.sk_ASN1_INTEGER_num(un.noticeref.noticenos)
notice_numbers = []
for i in range(num):
asn1_int = backend._lib.sk_ASN1_INTEGER_value(
@@ -319,9 +313,7 @@ def _decode_user_notice(backend, un):
notice_num = _asn1_integer_to_int(backend, asn1_int)
notice_numbers.append(notice_num)
- notice_reference = x509.NoticeReference(
- organization, notice_numbers
- )
+ notice_reference = x509.NoticeReference(organization, notice_numbers)
return x509.UserNotice(notice_reference, explicit_text)
@@ -364,9 +356,7 @@ def _decode_authority_key_identifier(backend, akid):
)[:]
if akid.issuer != backend._ffi.NULL:
- authority_cert_issuer = _decode_general_names(
- backend, akid.issuer
- )
+ authority_cert_issuer = _decode_general_names(backend, akid.issuer)
authority_cert_serial_number = _asn1_integer_to_int_or_none(
backend, akid.serial
@@ -377,22 +367,40 @@ def _decode_authority_key_identifier(backend, akid):
)
-def _decode_authority_information_access(backend, aia):
- aia = backend._ffi.cast("Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia)
- aia = backend._ffi.gc(aia, backend._lib.sk_ACCESS_DESCRIPTION_free)
- num = backend._lib.sk_ACCESS_DESCRIPTION_num(aia)
+def _decode_information_access(backend, ia):
+ ia = backend._ffi.cast("Cryptography_STACK_OF_ACCESS_DESCRIPTION *", ia)
+ ia = backend._ffi.gc(
+ ia,
+ lambda x: backend._lib.sk_ACCESS_DESCRIPTION_pop_free(
+ x,
+ backend._ffi.addressof(
+ backend._lib._original_lib, "ACCESS_DESCRIPTION_free"
+ ),
+ ),
+ )
+ num = backend._lib.sk_ACCESS_DESCRIPTION_num(ia)
access_descriptions = []
for i in range(num):
- ad = backend._lib.sk_ACCESS_DESCRIPTION_value(aia, i)
+ ad = backend._lib.sk_ACCESS_DESCRIPTION_value(ia, i)
backend.openssl_assert(ad.method != backend._ffi.NULL)
oid = x509.ObjectIdentifier(_obj2txt(backend, ad.method))
backend.openssl_assert(ad.location != backend._ffi.NULL)
gn = _decode_general_name(backend, ad.location)
access_descriptions.append(x509.AccessDescription(oid, gn))
+ return access_descriptions
+
+
+def _decode_authority_information_access(backend, aia):
+ access_descriptions = _decode_information_access(backend, aia)
return x509.AuthorityInformationAccess(access_descriptions)
+def _decode_subject_information_access(backend, aia):
+ access_descriptions = _decode_information_access(backend, aia)
+ return x509.SubjectInformationAccess(access_descriptions)
+
+
def _decode_key_usage(backend, bit_string):
bit_string = backend._ffi.cast("ASN1_BIT_STRING *", bit_string)
bit_string = backend._ffi.gc(bit_string, backend._lib.ASN1_BIT_STRING_free)
@@ -415,7 +423,7 @@ def _decode_key_usage(backend, bit_string):
key_cert_sign,
crl_sign,
encipher_only,
- decipher_only
+ decipher_only,
)
@@ -483,8 +491,13 @@ def _decode_issuing_dist_point(backend, idp):
only_some_reasons = None
return x509.IssuingDistributionPoint(
- full_name, relative_name, only_user, only_ca, only_some_reasons,
- indirect_crl, only_attr
+ full_name,
+ relative_name,
+ only_user,
+ only_ca,
+ only_some_reasons,
+ indirect_crl,
+ only_attr,
)
@@ -605,13 +618,9 @@ def _decode_distpoint(backend, distpoint):
rnum = backend._lib.sk_X509_NAME_ENTRY_num(rns)
attributes = set()
for i in range(rnum):
- rn = backend._lib.sk_X509_NAME_ENTRY_value(
- rns, i
- )
+ rn = backend._lib.sk_X509_NAME_ENTRY_value(rns, i)
backend.openssl_assert(rn != backend._ffi.NULL)
- attributes.add(
- _decode_x509_name_entry(backend, rn)
- )
+ attributes.add(_decode_x509_name_entry(backend, rn))
relative_name = x509.RelativeDistinguishedName(attributes)
@@ -635,10 +644,11 @@ def _decode_inhibit_any_policy(backend, asn1_int):
return x509.InhibitAnyPolicy(skip_certs)
-def _decode_precert_signed_certificate_timestamps(backend, asn1_scts):
+def _decode_scts(backend, asn1_scts):
from cryptography.hazmat.backends.openssl.x509 import (
- _SignedCertificateTimestamp
+ _SignedCertificateTimestamp,
)
+
asn1_scts = backend._ffi.cast("Cryptography_STACK_OF_SCT *", asn1_scts)
asn1_scts = backend._ffi.gc(asn1_scts, backend._lib.SCT_LIST_free)
@@ -647,7 +657,17 @@ def _decode_precert_signed_certificate_timestamps(backend, asn1_scts):
sct = backend._lib.sk_SCT_value(asn1_scts, i)
scts.append(_SignedCertificateTimestamp(backend, asn1_scts, sct))
- return x509.PrecertificateSignedCertificateTimestamps(scts)
+ return scts
+
+
+def _decode_precert_signed_certificate_timestamps(backend, asn1_scts):
+ return x509.PrecertificateSignedCertificateTimestamps(
+ _decode_scts(backend, asn1_scts)
+ )
+
+
+def _decode_signed_certificate_timestamps(backend, asn1_scts):
+ return x509.SignedCertificateTimestamps(_decode_scts(backend, asn1_scts))
# CRLReason ::= ENUMERATED {
@@ -686,7 +706,7 @@ _CRL_ENTRY_REASON_ENUM_TO_CODE = {
x509.ReasonFlags.certificate_hold: 6,
x509.ReasonFlags.remove_from_crl: 8,
x509.ReasonFlags.privilege_withdrawn: 9,
- x509.ReasonFlags.aa_compromise: 10
+ x509.ReasonFlags.aa_compromise: 10,
}
@@ -698,13 +718,11 @@ def _decode_crl_reason(backend, enum):
try:
return x509.CRLReason(_CRL_ENTRY_REASON_CODE_TO_ENUM[code])
except KeyError:
- raise ValueError("Unsupported reason code: {0}".format(code))
+ raise ValueError("Unsupported reason code: {}".format(code))
def _decode_invalidity_date(backend, inv_date):
- generalized_time = backend._ffi.cast(
- "ASN1_GENERALIZEDTIME *", inv_date
- )
+ generalized_time = backend._ffi.cast("ASN1_GENERALIZEDTIME *", inv_date)
generalized_time = backend._ffi.gc(
generalized_time, backend._lib.ASN1_GENERALIZEDTIME_free
)
@@ -758,14 +776,14 @@ def _asn1_string_to_utf8(backend, asn1_string):
res = backend._lib.ASN1_STRING_to_UTF8(buf, asn1_string)
if res == -1:
raise ValueError(
- "Unsupported ASN1 string type. Type: {0}".format(asn1_string.type)
+ "Unsupported ASN1 string type. Type: {}".format(asn1_string.type)
)
backend.openssl_assert(buf[0] != backend._ffi.NULL)
buf = backend._ffi.gc(
buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0])
)
- return backend._ffi.buffer(buf[0], res)[:].decode('utf8')
+ return backend._ffi.buffer(buf[0], res)[:].decode("utf8")
def _parse_asn1_time(backend, asn1_time):
@@ -799,7 +817,7 @@ def _decode_nonce(backend, nonce):
return x509.OCSPNonce(_asn1_string_to_bytes(backend, nonce))
-_EXTENSION_HANDLERS_NO_SCT = {
+_EXTENSION_HANDLERS_BASE = {
ExtensionOID.BASIC_CONSTRAINTS: _decode_basic_constraints,
ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier,
ExtensionOID.KEY_USAGE: _decode_key_usage,
@@ -809,6 +827,9 @@ _EXTENSION_HANDLERS_NO_SCT = {
ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
_decode_authority_information_access
),
+ ExtensionOID.SUBJECT_INFORMATION_ACCESS: (
+ _decode_subject_information_access
+ ),
ExtensionOID.CERTIFICATE_POLICIES: _decode_certificate_policies,
ExtensionOID.CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points,
ExtensionOID.FRESHEST_CRL: _decode_freshest_crl,
@@ -818,11 +839,11 @@ _EXTENSION_HANDLERS_NO_SCT = {
ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints,
ExtensionOID.POLICY_CONSTRAINTS: _decode_policy_constraints,
}
-_EXTENSION_HANDLERS = _EXTENSION_HANDLERS_NO_SCT.copy()
-_EXTENSION_HANDLERS[
- ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
-] = _decode_precert_signed_certificate_timestamps
-
+_EXTENSION_HANDLERS_SCT = {
+ ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: (
+ _decode_precert_signed_certificate_timestamps
+ )
+}
_REVOKED_EXTENSION_HANDLERS = {
CRLEntryExtensionOID.CRL_REASON: _decode_crl_reason,
@@ -839,6 +860,7 @@ _CRL_EXTENSION_HANDLERS = {
_decode_authority_information_access
),
ExtensionOID.ISSUING_DISTRIBUTION_POINT: _decode_issuing_dist_point,
+ ExtensionOID.FRESHEST_CRL: _decode_freshest_crl,
}
_OCSP_REQ_EXTENSION_HANDLERS = {
@@ -849,44 +871,8 @@ _OCSP_BASICRESP_EXTENSION_HANDLERS = {
OCSPExtensionOID.NONCE: _decode_nonce,
}
-_CERTIFICATE_EXTENSION_PARSER_NO_SCT = _X509ExtensionParser(
- ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x),
- get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i),
- handlers=_EXTENSION_HANDLERS_NO_SCT
-)
-
-_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser(
- ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x),
- get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i),
- handlers=_EXTENSION_HANDLERS
-)
-
-_CSR_EXTENSION_PARSER = _X509ExtensionParser(
- ext_count=lambda backend, x: backend._lib.sk_X509_EXTENSION_num(x),
- get_ext=lambda backend, x, i: backend._lib.sk_X509_EXTENSION_value(x, i),
- handlers=_EXTENSION_HANDLERS
-)
-
-_REVOKED_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser(
- ext_count=lambda backend, x: backend._lib.X509_REVOKED_get_ext_count(x),
- get_ext=lambda backend, x, i: backend._lib.X509_REVOKED_get_ext(x, i),
- handlers=_REVOKED_EXTENSION_HANDLERS,
-)
-
-_CRL_EXTENSION_PARSER = _X509ExtensionParser(
- ext_count=lambda backend, x: backend._lib.X509_CRL_get_ext_count(x),
- get_ext=lambda backend, x, i: backend._lib.X509_CRL_get_ext(x, i),
- handlers=_CRL_EXTENSION_HANDLERS,
-)
-
-_OCSP_REQ_EXT_PARSER = _X509ExtensionParser(
- ext_count=lambda backend, x: backend._lib.OCSP_REQUEST_get_ext_count(x),
- get_ext=lambda backend, x, i: backend._lib.OCSP_REQUEST_get_ext(x, i),
- handlers=_OCSP_REQ_EXTENSION_HANDLERS,
-)
-
-_OCSP_BASICRESP_EXT_PARSER = _X509ExtensionParser(
- ext_count=lambda backend, x: backend._lib.OCSP_BASICRESP_get_ext_count(x),
- get_ext=lambda backend, x, i: backend._lib.OCSP_BASICRESP_get_ext(x, i),
- handlers=_OCSP_BASICRESP_EXTENSION_HANDLERS,
-)
+_OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT = {
+ ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: (
+ _decode_signed_certificate_timestamps
+ )
+}
diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py
index 095f06233..2862676c6 100644
--- a/src/cryptography/hazmat/backends/openssl/dh.py
+++ b/src/cryptography/hazmat/backends/openssl/dh.py
@@ -17,8 +17,8 @@ def _dh_params_dup(dh_cdata, backend):
param_cdata = lib.DHparams_dup(dh_cdata)
backend.openssl_assert(param_cdata != ffi.NULL)
param_cdata = ffi.gc(param_cdata, lib.DH_free)
- if lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102:
- # In OpenSSL versions < 1.0.2 or libressl DHparams_dup don't copy q
+ if lib.CRYPTOGRAPHY_IS_LIBRESSL:
+ # In libressl DHparams_dup don't copy q
q = ffi.new("BIGNUM **")
lib.DH_get0_pqg(dh_cdata, ffi.NULL, q, ffi.NULL)
q_dup = lib.BN_dup(q[0])
@@ -53,7 +53,7 @@ class _DHParameters(object):
return dh.DHParameterNumbers(
p=self._backend._bn_to_int(p[0]),
g=self._backend._bn_to_int(g[0]),
- q=q_val
+ q=q_val,
)
def generate_private_key(self):
@@ -61,44 +61,27 @@ class _DHParameters(object):
def parameter_bytes(self, encoding, format):
if format is not serialization.ParameterFormat.PKCS3:
- raise ValueError(
- "Only PKCS3 serialization is supported"
- )
+ raise ValueError("Only PKCS3 serialization is supported")
if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX:
q = self._backend._ffi.new("BIGNUM **")
- self._backend._lib.DH_get0_pqg(self._dh_cdata,
- self._backend._ffi.NULL,
- q,
- self._backend._ffi.NULL)
+ self._backend._lib.DH_get0_pqg(
+ self._dh_cdata,
+ self._backend._ffi.NULL,
+ q,
+ self._backend._ffi.NULL,
+ )
if q[0] != self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
"DH X9.42 serialization is not supported",
- _Reasons.UNSUPPORTED_SERIALIZATION)
+ _Reasons.UNSUPPORTED_SERIALIZATION,
+ )
- return self._backend._parameter_bytes(
- encoding,
- format,
- self._dh_cdata
- )
-
-
-def _handle_dh_compute_key_error(errors, backend):
- lib = backend._lib
-
- backend.openssl_assert(
- errors[0]._lib_reason_match(
- lib.ERR_LIB_DH, lib.DH_R_INVALID_PUBKEY
- )
- )
-
- raise ValueError("Public key value is invalid for this exchange.")
+ return self._backend._parameter_bytes(encoding, format, self._dh_cdata)
def _get_dh_num_bits(backend, dh_cdata):
p = backend._ffi.new("BIGNUM **")
- backend._lib.DH_get0_pqg(dh_cdata, p,
- backend._ffi.NULL,
- backend._ffi.NULL)
+ backend._lib.DH_get0_pqg(dh_cdata, p, backend._ffi.NULL, backend._ffi.NULL)
backend.openssl_assert(p[0] != backend._ffi.NULL)
return backend._lib.BN_num_bits(p[0])
@@ -136,29 +119,32 @@ class _DHPrivateKey(object):
parameter_numbers=dh.DHParameterNumbers(
p=self._backend._bn_to_int(p[0]),
g=self._backend._bn_to_int(g[0]),
- q=q_val
+ q=q_val,
),
- y=self._backend._bn_to_int(pub_key[0])
+ y=self._backend._bn_to_int(pub_key[0]),
),
- x=self._backend._bn_to_int(priv_key[0])
+ x=self._backend._bn_to_int(priv_key[0]),
)
def exchange(self, peer_public_key):
buf = self._backend._ffi.new("unsigned char[]", self._key_size_bytes)
pub_key = self._backend._ffi.new("BIGNUM **")
- self._backend._lib.DH_get0_key(peer_public_key._dh_cdata, pub_key,
- self._backend._ffi.NULL)
+ self._backend._lib.DH_get0_key(
+ peer_public_key._dh_cdata, pub_key, self._backend._ffi.NULL
+ )
self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL)
res = self._backend._lib.DH_compute_key(
- buf,
- pub_key[0],
- self._dh_cdata
+ buf, pub_key[0], self._dh_cdata
)
if res == -1:
- errors = self._backend._consume_errors()
- return _handle_dh_compute_key_error(errors, self._backend)
+ errors_with_text = self._backend._consume_errors_with_text()
+ raise ValueError(
+ "Error computing shared key. Public key is likely invalid "
+ "for this exchange.",
+ errors_with_text,
+ )
else:
self._backend.openssl_assert(res >= 1)
@@ -173,15 +159,16 @@ class _DHPrivateKey(object):
def public_key(self):
dh_cdata = _dh_params_dup(self._dh_cdata, self._backend)
pub_key = self._backend._ffi.new("BIGNUM **")
- self._backend._lib.DH_get0_key(self._dh_cdata,
- pub_key, self._backend._ffi.NULL)
+ self._backend._lib.DH_get0_key(
+ self._dh_cdata, pub_key, self._backend._ffi.NULL
+ )
self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL)
pub_key_dup = self._backend._lib.BN_dup(pub_key[0])
self._backend.openssl_assert(pub_key_dup != self._backend._ffi.NULL)
- res = self._backend._lib.DH_set0_key(dh_cdata,
- pub_key_dup,
- self._backend._ffi.NULL)
+ res = self._backend._lib.DH_set0_key(
+ dh_cdata, pub_key_dup, self._backend._ffi.NULL
+ )
self._backend.openssl_assert(res == 1)
evp_pkey = self._backend._dh_cdata_to_evp_pkey(dh_cdata)
return _DHPublicKey(self._backend, dh_cdata, evp_pkey)
@@ -196,21 +183,25 @@ class _DHPrivateKey(object):
)
if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX:
q = self._backend._ffi.new("BIGNUM **")
- self._backend._lib.DH_get0_pqg(self._dh_cdata,
- self._backend._ffi.NULL,
- q,
- self._backend._ffi.NULL)
+ self._backend._lib.DH_get0_pqg(
+ self._dh_cdata,
+ self._backend._ffi.NULL,
+ q,
+ self._backend._ffi.NULL,
+ )
if q[0] != self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
"DH X9.42 serialization is not supported",
- _Reasons.UNSUPPORTED_SERIALIZATION)
+ _Reasons.UNSUPPORTED_SERIALIZATION,
+ )
return self._backend._private_key_bytes(
encoding,
format,
encryption_algorithm,
+ self,
self._evp_pkey,
- self._dh_cdata
+ self._dh_cdata,
)
@@ -238,16 +229,17 @@ class _DHPublicKey(object):
else:
q_val = self._backend._bn_to_int(q[0])
pub_key = self._backend._ffi.new("BIGNUM **")
- self._backend._lib.DH_get0_key(self._dh_cdata,
- pub_key, self._backend._ffi.NULL)
+ self._backend._lib.DH_get0_key(
+ self._dh_cdata, pub_key, self._backend._ffi.NULL
+ )
self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL)
return dh.DHPublicNumbers(
parameter_numbers=dh.DHParameterNumbers(
p=self._backend._bn_to_int(p[0]),
g=self._backend._bn_to_int(g[0]),
- q=q_val
+ q=q_val,
),
- y=self._backend._bn_to_int(pub_key[0])
+ y=self._backend._bn_to_int(pub_key[0]),
)
def parameters(self):
@@ -262,19 +254,18 @@ class _DHPublicKey(object):
if not self._backend._lib.Cryptography_HAS_EVP_PKEY_DHX:
q = self._backend._ffi.new("BIGNUM **")
- self._backend._lib.DH_get0_pqg(self._dh_cdata,
- self._backend._ffi.NULL,
- q,
- self._backend._ffi.NULL)
+ self._backend._lib.DH_get0_pqg(
+ self._dh_cdata,
+ self._backend._ffi.NULL,
+ q,
+ self._backend._ffi.NULL,
+ )
if q[0] != self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
"DH X9.42 serialization is not supported",
- _Reasons.UNSUPPORTED_SERIALIZATION)
+ _Reasons.UNSUPPORTED_SERIALIZATION,
+ )
return self._backend._public_key_bytes(
- encoding,
- format,
- self,
- self._evp_pkey,
- None
+ encoding, format, self, self._evp_pkey, None
)
diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py
index de61f0894..0c5faba18 100644
--- a/src/cryptography/hazmat/backends/openssl/dsa.py
+++ b/src/cryptography/hazmat/backends/openssl/dsa.py
@@ -7,12 +7,15 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends.openssl.utils import (
- _calculate_digest_and_algorithm, _check_not_prehashed,
- _warn_sign_verify_deprecated
+ _calculate_digest_and_algorithm,
+ _check_not_prehashed,
+ _warn_sign_verify_deprecated,
)
-from cryptography.hazmat.primitives import hashes, serialization
+from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import (
- AsymmetricSignatureContext, AsymmetricVerificationContext, dsa
+ AsymmetricSignatureContext,
+ AsymmetricVerificationContext,
+ dsa,
)
@@ -29,7 +32,7 @@ def _dsa_sig_sign(backend, private_key, data):
backend.openssl_assert(res == 1)
backend.openssl_assert(buflen[0])
- return backend._ffi.buffer(sig_buf)[:buflen[0]]
+ return backend._ffi.buffer(sig_buf)[: buflen[0]]
def _dsa_sig_verify(backend, public_key, signature, data):
@@ -98,7 +101,7 @@ class _DSAParameters(object):
return dsa.DSAParameterNumbers(
p=self._backend._bn_to_int(p[0]),
q=self._backend._bn_to_int(q[0]),
- g=self._backend._bn_to_int(g[0])
+ g=self._backend._bn_to_int(g[0]),
)
def generate_private_key(self):
@@ -144,11 +147,11 @@ class _DSAPrivateKey(object):
parameter_numbers=dsa.DSAParameterNumbers(
p=self._backend._bn_to_int(p[0]),
q=self._backend._bn_to_int(q[0]),
- g=self._backend._bn_to_int(g[0])
+ g=self._backend._bn_to_int(g[0]),
),
- y=self._backend._bn_to_int(pub_key[0])
+ y=self._backend._bn_to_int(pub_key[0]),
),
- x=self._backend._bn_to_int(priv_key[0])
+ x=self._backend._bn_to_int(priv_key[0]),
)
def public_key(self):
@@ -183,8 +186,9 @@ class _DSAPrivateKey(object):
encoding,
format,
encryption_algorithm,
+ self,
self._evp_pkey,
- self._dsa_cdata
+ self._dsa_cdata,
)
def sign(self, data, algorithm):
@@ -235,9 +239,9 @@ class _DSAPublicKey(object):
parameter_numbers=dsa.DSAParameterNumbers(
p=self._backend._bn_to_int(p[0]),
q=self._backend._bn_to_int(q[0]),
- g=self._backend._bn_to_int(g[0])
+ g=self._backend._bn_to_int(g[0]),
),
- y=self._backend._bn_to_int(pub_key[0])
+ y=self._backend._bn_to_int(pub_key[0]),
)
def parameters(self):
@@ -248,17 +252,8 @@ class _DSAPublicKey(object):
return _DSAParameters(self._backend, dsa_cdata)
def public_bytes(self, encoding, format):
- if format is serialization.PublicFormat.PKCS1:
- raise ValueError(
- "DSA public keys do not support PKCS1 serialization"
- )
-
return self._backend._public_key_bytes(
- encoding,
- format,
- self,
- self._evp_pkey,
- None
+ encoding, format, self, self._evp_pkey, None
)
def verify(self, signature, data, algorithm):
diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py
index a8d69bdf9..05d32baba 100644
--- a/src/cryptography/hazmat/backends/openssl/ec.py
+++ b/src/cryptography/hazmat/backends/openssl/ec.py
@@ -6,15 +6,20 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import (
- InvalidSignature, UnsupportedAlgorithm, _Reasons
+ InvalidSignature,
+ UnsupportedAlgorithm,
+ _Reasons,
)
from cryptography.hazmat.backends.openssl.utils import (
- _calculate_digest_and_algorithm, _check_not_prehashed,
- _warn_sign_verify_deprecated
+ _calculate_digest_and_algorithm,
+ _check_not_prehashed,
+ _warn_sign_verify_deprecated,
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import (
- AsymmetricSignatureContext, AsymmetricVerificationContext, ec
+ AsymmetricSignatureContext,
+ AsymmetricVerificationContext,
+ ec,
)
@@ -22,7 +27,8 @@ def _check_signature_algorithm(signature_algorithm):
if not isinstance(signature_algorithm, ec.ECDSA):
raise UnsupportedAlgorithm(
"Unsupported elliptic curve signature algorithm.",
- _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+ )
def _ec_key_curve_sn(backend, ec_key):
@@ -34,14 +40,24 @@ def _ec_key_curve_sn(backend, ec_key):
# an error for now.
if nid == backend._lib.NID_undef:
raise NotImplementedError(
- "ECDSA certificates with unnamed curves are unsupported "
- "at this time"
+ "ECDSA keys with unnamed curves are unsupported at this time"
+ )
+
+ # This is like the above check, but it also catches the case where you
+ # explicitly encoded a curve with the same parameters as a named curve.
+ # Don't do that.
+ if (
+ not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
+ and backend._lib.EC_GROUP_get_asn1_flag(group) == 0
+ ):
+ raise NotImplementedError(
+ "ECDSA keys with unnamed curves are unsupported at this time"
)
curve_name = backend._lib.OBJ_nid2sn(nid)
backend.openssl_assert(curve_name != backend._ffi.NULL)
- sn = backend._ffi.string(curve_name).decode('ascii')
+ sn = backend._ffi.string(curve_name).decode("ascii")
return sn
@@ -62,8 +78,8 @@ def _sn_to_elliptic_curve(backend, sn):
return ec._CURVE_TYPES[sn]()
except KeyError:
raise UnsupportedAlgorithm(
- "{0} is not a supported elliptic curve".format(sn),
- _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+ "{} is not a supported elliptic curve".format(sn),
+ _Reasons.UNSUPPORTED_ELLIPTIC_CURVE,
)
@@ -77,7 +93,7 @@ def _ecdsa_sig_sign(backend, private_key, data):
0, data, len(data), sigbuf, siglen_ptr, private_key._ec_key
)
backend.openssl_assert(res == 1)
- return backend._ffi.buffer(sigbuf)[:siglen_ptr[0]]
+ return backend._ffi.buffer(sigbuf)[: siglen_ptr[0]]
def _ecdsa_sig_verify(backend, public_key, signature, data):
@@ -127,12 +143,12 @@ class _ECDSAVerificationContext(object):
class _EllipticCurvePrivateKey(object):
def __init__(self, backend, ec_key_cdata, evp_pkey):
self._backend = backend
- _mark_asn1_named_ec_curve(backend, ec_key_cdata)
self._ec_key = ec_key_cdata
self._evp_pkey = evp_pkey
sn = _ec_key_curve_sn(backend, ec_key_cdata)
self._curve = _sn_to_elliptic_curve(backend, sn)
+ _mark_asn1_named_ec_curve(backend, ec_key_cdata)
curve = utils.read_only_property("_curve")
@@ -156,7 +172,7 @@ class _EllipticCurvePrivateKey(object):
):
raise UnsupportedAlgorithm(
"This backend does not support the ECDH algorithm.",
- _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+ _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
)
if peer_public_key.curve.name != self.curve.name:
@@ -183,12 +199,7 @@ class _EllipticCurvePrivateKey(object):
self._backend.openssl_assert(group != self._backend._ffi.NULL)
curve_nid = self._backend._lib.EC_GROUP_get_curve_name(group)
-
- public_ec_key = self._backend._lib.EC_KEY_new_by_curve_name(curve_nid)
- self._backend.openssl_assert(public_ec_key != self._backend._ffi.NULL)
- public_ec_key = self._backend._ffi.gc(
- public_ec_key, self._backend._lib.EC_KEY_free
- )
+ public_ec_key = self._backend._ec_key_new_by_curve_nid(curve_nid)
point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
self._backend.openssl_assert(point != self._backend._ffi.NULL)
@@ -205,7 +216,7 @@ class _EllipticCurvePrivateKey(object):
private_value = self._backend._bn_to_int(bn)
return ec.EllipticCurvePrivateNumbers(
private_value=private_value,
- public_numbers=self.public_key().public_numbers()
+ public_numbers=self.public_key().public_numbers(),
)
def private_bytes(self, encoding, format, encryption_algorithm):
@@ -213,8 +224,9 @@ class _EllipticCurvePrivateKey(object):
encoding,
format,
encryption_algorithm,
+ self,
self._evp_pkey,
- self._ec_key
+ self._ec_key,
)
def sign(self, data, signature_algorithm):
@@ -229,12 +241,12 @@ class _EllipticCurvePrivateKey(object):
class _EllipticCurvePublicKey(object):
def __init__(self, backend, ec_key_cdata, evp_pkey):
self._backend = backend
- _mark_asn1_named_ec_curve(backend, ec_key_cdata)
self._ec_key = ec_key_cdata
self._evp_pkey = evp_pkey
sn = _ec_key_curve_sn(backend, ec_key_cdata)
self._curve = _sn_to_elliptic_curve(backend, sn)
+ _mark_asn1_named_ec_curve(backend, ec_key_cdata)
curve = utils.read_only_property("_curve")
@@ -253,8 +265,8 @@ class _EllipticCurvePublicKey(object):
)
def public_numbers(self):
- get_func, group = (
- self._backend._ec_key_determine_group_get_func(self._ec_key)
+ get_func, group = self._backend._ec_key_determine_group_get_func(
+ self._ec_key
)
point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
self._backend.openssl_assert(point != self._backend._ffi.NULL)
@@ -269,11 +281,7 @@ class _EllipticCurvePublicKey(object):
x = self._backend._bn_to_int(bn_x)
y = self._backend._bn_to_int(bn_y)
- return ec.EllipticCurvePublicNumbers(
- x=x,
- y=y,
- curve=self._curve
- )
+ return ec.EllipticCurvePublicNumbers(x=x, y=y, curve=self._curve)
def _encode_point(self, format):
if format is serialization.PublicFormat.CompressedPoint:
@@ -300,22 +308,15 @@ class _EllipticCurvePublicKey(object):
return self._backend._ffi.buffer(buf)[:]
def public_bytes(self, encoding, format):
- if format is serialization.PublicFormat.PKCS1:
- raise ValueError(
- "EC public keys do not support PKCS1 serialization"
- )
if (
- encoding is serialization.Encoding.X962 or
- format is serialization.PublicFormat.CompressedPoint or
- format is serialization.PublicFormat.UncompressedPoint
+ encoding is serialization.Encoding.X962
+ or format is serialization.PublicFormat.CompressedPoint
+ or format is serialization.PublicFormat.UncompressedPoint
):
- if (
- encoding is not serialization.Encoding.X962 or
- format not in (
- serialization.PublicFormat.CompressedPoint,
- serialization.PublicFormat.UncompressedPoint
- )
+ if encoding is not serialization.Encoding.X962 or format not in (
+ serialization.PublicFormat.CompressedPoint,
+ serialization.PublicFormat.UncompressedPoint,
):
raise ValueError(
"X962 encoding must be used with CompressedPoint or "
@@ -325,11 +326,7 @@ class _EllipticCurvePublicKey(object):
return self._encode_point(format)
else:
return self._backend._public_key_bytes(
- encoding,
- format,
- self,
- self._evp_pkey,
- None
+ encoding, format, self, self._evp_pkey, None
)
def verify(self, signature, data, signature_algorithm):
diff --git a/src/cryptography/hazmat/backends/openssl/ed25519.py b/src/cryptography/hazmat/backends/openssl/ed25519.py
new file mode 100644
index 000000000..13bec3af1
--- /dev/null
+++ b/src/cryptography/hazmat/backends/openssl/ed25519.py
@@ -0,0 +1,145 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+from cryptography import exceptions, utils
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.ed25519 import (
+ Ed25519PrivateKey,
+ Ed25519PublicKey,
+ _ED25519_KEY_SIZE,
+ _ED25519_SIG_SIZE,
+)
+
+
+@utils.register_interface(Ed25519PublicKey)
+class _Ed25519PublicKey(object):
+ def __init__(self, backend, evp_pkey):
+ self._backend = backend
+ self._evp_pkey = evp_pkey
+
+ def public_bytes(self, encoding, format):
+ if (
+ encoding is serialization.Encoding.Raw
+ or format is serialization.PublicFormat.Raw
+ ):
+ if (
+ encoding is not serialization.Encoding.Raw
+ or format is not serialization.PublicFormat.Raw
+ ):
+ raise ValueError(
+ "When using Raw both encoding and format must be Raw"
+ )
+
+ return self._raw_public_bytes()
+
+ return self._backend._public_key_bytes(
+ encoding, format, self, self._evp_pkey, None
+ )
+
+ def _raw_public_bytes(self):
+ buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE)
+ buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE)
+ res = self._backend._lib.EVP_PKEY_get_raw_public_key(
+ self._evp_pkey, buf, buflen
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE)
+ return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:]
+
+ def verify(self, signature, data):
+ evp_md_ctx = self._backend._lib.EVP_MD_CTX_new()
+ self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL)
+ evp_md_ctx = self._backend._ffi.gc(
+ evp_md_ctx, self._backend._lib.EVP_MD_CTX_free
+ )
+ res = self._backend._lib.EVP_DigestVerifyInit(
+ evp_md_ctx,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._evp_pkey,
+ )
+ self._backend.openssl_assert(res == 1)
+ res = self._backend._lib.EVP_DigestVerify(
+ evp_md_ctx, signature, len(signature), data, len(data)
+ )
+ if res != 1:
+ self._backend._consume_errors()
+ raise exceptions.InvalidSignature
+
+
+@utils.register_interface(Ed25519PrivateKey)
+class _Ed25519PrivateKey(object):
+ def __init__(self, backend, evp_pkey):
+ self._backend = backend
+ self._evp_pkey = evp_pkey
+
+ def public_key(self):
+ buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE)
+ buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE)
+ res = self._backend._lib.EVP_PKEY_get_raw_public_key(
+ self._evp_pkey, buf, buflen
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE)
+ public_bytes = self._backend._ffi.buffer(buf)[:]
+ return self._backend.ed25519_load_public_bytes(public_bytes)
+
+ def sign(self, data):
+ evp_md_ctx = self._backend._lib.EVP_MD_CTX_new()
+ self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL)
+ evp_md_ctx = self._backend._ffi.gc(
+ evp_md_ctx, self._backend._lib.EVP_MD_CTX_free
+ )
+ res = self._backend._lib.EVP_DigestSignInit(
+ evp_md_ctx,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._evp_pkey,
+ )
+ self._backend.openssl_assert(res == 1)
+ buf = self._backend._ffi.new("unsigned char[]", _ED25519_SIG_SIZE)
+ buflen = self._backend._ffi.new("size_t *", len(buf))
+ res = self._backend._lib.EVP_DigestSign(
+ evp_md_ctx, buf, buflen, data, len(data)
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(buflen[0] == _ED25519_SIG_SIZE)
+ return self._backend._ffi.buffer(buf, buflen[0])[:]
+
+ def private_bytes(self, encoding, format, encryption_algorithm):
+ if (
+ encoding is serialization.Encoding.Raw
+ or format is serialization.PublicFormat.Raw
+ ):
+ if (
+ format is not serialization.PrivateFormat.Raw
+ or encoding is not serialization.Encoding.Raw
+ or not isinstance(
+ encryption_algorithm, serialization.NoEncryption
+ )
+ ):
+ raise ValueError(
+ "When using Raw both encoding and format must be Raw "
+ "and encryption_algorithm must be NoEncryption()"
+ )
+
+ return self._raw_private_bytes()
+
+ return self._backend._private_key_bytes(
+ encoding, format, encryption_algorithm, self, self._evp_pkey, None
+ )
+
+ def _raw_private_bytes(self):
+ buf = self._backend._ffi.new("unsigned char []", _ED25519_KEY_SIZE)
+ buflen = self._backend._ffi.new("size_t *", _ED25519_KEY_SIZE)
+ res = self._backend._lib.EVP_PKEY_get_raw_private_key(
+ self._evp_pkey, buf, buflen
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(buflen[0] == _ED25519_KEY_SIZE)
+ return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:]
diff --git a/src/cryptography/hazmat/backends/openssl/ed448.py b/src/cryptography/hazmat/backends/openssl/ed448.py
new file mode 100644
index 000000000..6512770e5
--- /dev/null
+++ b/src/cryptography/hazmat/backends/openssl/ed448.py
@@ -0,0 +1,146 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+from cryptography import exceptions, utils
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.ed448 import (
+ Ed448PrivateKey,
+ Ed448PublicKey,
+)
+
+_ED448_KEY_SIZE = 57
+_ED448_SIG_SIZE = 114
+
+
+@utils.register_interface(Ed448PublicKey)
+class _Ed448PublicKey(object):
+ def __init__(self, backend, evp_pkey):
+ self._backend = backend
+ self._evp_pkey = evp_pkey
+
+ def public_bytes(self, encoding, format):
+ if (
+ encoding is serialization.Encoding.Raw
+ or format is serialization.PublicFormat.Raw
+ ):
+ if (
+ encoding is not serialization.Encoding.Raw
+ or format is not serialization.PublicFormat.Raw
+ ):
+ raise ValueError(
+ "When using Raw both encoding and format must be Raw"
+ )
+
+ return self._raw_public_bytes()
+
+ return self._backend._public_key_bytes(
+ encoding, format, self, self._evp_pkey, None
+ )
+
+ def _raw_public_bytes(self):
+ buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE)
+ buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE)
+ res = self._backend._lib.EVP_PKEY_get_raw_public_key(
+ self._evp_pkey, buf, buflen
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE)
+ return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:]
+
+ def verify(self, signature, data):
+ evp_md_ctx = self._backend._lib.EVP_MD_CTX_new()
+ self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL)
+ evp_md_ctx = self._backend._ffi.gc(
+ evp_md_ctx, self._backend._lib.EVP_MD_CTX_free
+ )
+ res = self._backend._lib.EVP_DigestVerifyInit(
+ evp_md_ctx,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._evp_pkey,
+ )
+ self._backend.openssl_assert(res == 1)
+ res = self._backend._lib.EVP_DigestVerify(
+ evp_md_ctx, signature, len(signature), data, len(data)
+ )
+ if res != 1:
+ self._backend._consume_errors()
+ raise exceptions.InvalidSignature
+
+
+@utils.register_interface(Ed448PrivateKey)
+class _Ed448PrivateKey(object):
+ def __init__(self, backend, evp_pkey):
+ self._backend = backend
+ self._evp_pkey = evp_pkey
+
+ def public_key(self):
+ buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE)
+ buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE)
+ res = self._backend._lib.EVP_PKEY_get_raw_public_key(
+ self._evp_pkey, buf, buflen
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE)
+ public_bytes = self._backend._ffi.buffer(buf)[:]
+ return self._backend.ed448_load_public_bytes(public_bytes)
+
+ def sign(self, data):
+ evp_md_ctx = self._backend._lib.EVP_MD_CTX_new()
+ self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL)
+ evp_md_ctx = self._backend._ffi.gc(
+ evp_md_ctx, self._backend._lib.EVP_MD_CTX_free
+ )
+ res = self._backend._lib.EVP_DigestSignInit(
+ evp_md_ctx,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._evp_pkey,
+ )
+ self._backend.openssl_assert(res == 1)
+ buf = self._backend._ffi.new("unsigned char[]", _ED448_SIG_SIZE)
+ buflen = self._backend._ffi.new("size_t *", len(buf))
+ res = self._backend._lib.EVP_DigestSign(
+ evp_md_ctx, buf, buflen, data, len(data)
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(buflen[0] == _ED448_SIG_SIZE)
+ return self._backend._ffi.buffer(buf, buflen[0])[:]
+
+ def private_bytes(self, encoding, format, encryption_algorithm):
+ if (
+ encoding is serialization.Encoding.Raw
+ or format is serialization.PublicFormat.Raw
+ ):
+ if (
+ format is not serialization.PrivateFormat.Raw
+ or encoding is not serialization.Encoding.Raw
+ or not isinstance(
+ encryption_algorithm, serialization.NoEncryption
+ )
+ ):
+ raise ValueError(
+ "When using Raw both encoding and format must be Raw "
+ "and encryption_algorithm must be NoEncryption()"
+ )
+
+ return self._raw_private_bytes()
+
+ return self._backend._private_key_bytes(
+ encoding, format, encryption_algorithm, self, self._evp_pkey, None
+ )
+
+ def _raw_private_bytes(self):
+ buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE)
+ buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE)
+ res = self._backend._lib.EVP_PKEY_get_raw_private_key(
+ self._evp_pkey, buf, buflen
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE)
+ return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:]
diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
index 355757624..0a33200bb 100644
--- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
@@ -11,12 +11,15 @@ import six
from cryptography import utils, x509
from cryptography.hazmat.backends.openssl.decode_asn1 import (
- _CRL_ENTRY_REASON_ENUM_TO_CODE, _DISTPOINT_TYPE_FULLNAME,
- _DISTPOINT_TYPE_RELATIVENAME
+ _CRL_ENTRY_REASON_ENUM_TO_CODE,
+ _DISTPOINT_TYPE_FULLNAME,
+ _DISTPOINT_TYPE_RELATIVENAME,
)
from cryptography.x509.name import _ASN1Type
from cryptography.x509.oid import (
- CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID,
+ CRLEntryExtensionOID,
+ ExtensionOID,
+ OCSPExtensionOID,
)
@@ -94,7 +97,8 @@ def _encode_name(backend, name):
name_entry, backend._lib.X509_NAME_ENTRY_free
)
res = backend._lib.X509_NAME_add_entry(
- subject, name_entry, -1, set_flag)
+ subject, name_entry, -1, set_flag
+ )
backend.openssl_assert(res == 1)
set_flag = -1
return subject
@@ -120,9 +124,11 @@ def _encode_sk_name_entry(backend, attributes):
def _encode_name_entry(backend, attribute):
if attribute._type is _ASN1Type.BMPString:
- value = attribute.value.encode('utf_16_be')
+ value = attribute.value.encode("utf_16_be")
+ elif attribute._type is _ASN1Type.UniversalString:
+ value = attribute.value.encode("utf_32_be")
else:
- value = attribute.value.encode('utf8')
+ value = attribute.value.encode("utf8")
obj = _txt2obj_gc(backend, attribute.oid.dotted_string)
@@ -172,9 +178,8 @@ def _encode_crl_reason(backend, crl_reason):
def _encode_invalidity_date(backend, invalidity_date):
time = backend._lib.ASN1_GENERALIZEDTIME_set(
- backend._ffi.NULL, calendar.timegm(
- invalidity_date.invalidity_date.timetuple()
- )
+ backend._ffi.NULL,
+ calendar.timegm(invalidity_date.invalidity_date.timetuple()),
)
backend.openssl_assert(time != backend._ffi.NULL)
time = backend._ffi.gc(time, backend._lib.ASN1_GENERALIZEDTIME_free)
@@ -255,7 +260,7 @@ def _txt2obj(backend, name):
Converts a Python string with an ASN.1 object ID in dotted form to a
ASN1_OBJECT.
"""
- name = name.encode('ascii')
+ name = name.encode("ascii")
obj = backend._lib.OBJ_txt2obj(name, 1)
backend.openssl_assert(obj != backend._ffi.NULL)
return obj
@@ -341,20 +346,27 @@ def _encode_basic_constraints(backend, basic_constraints):
return constraints
-def _encode_authority_information_access(backend, authority_info_access):
+def _encode_information_access(backend, info_access):
aia = backend._lib.sk_ACCESS_DESCRIPTION_new_null()
backend.openssl_assert(aia != backend._ffi.NULL)
aia = backend._ffi.gc(
- aia, backend._lib.sk_ACCESS_DESCRIPTION_free
+ aia,
+ lambda x: backend._lib.sk_ACCESS_DESCRIPTION_pop_free(
+ x,
+ backend._ffi.addressof(
+ backend._lib._original_lib, "ACCESS_DESCRIPTION_free"
+ ),
+ ),
)
- for access_description in authority_info_access:
+ for access_description in info_access:
ad = backend._lib.ACCESS_DESCRIPTION_new()
method = _txt2obj(
backend, access_description.access_method.dotted_string
)
- gn = _encode_general_name(backend, access_description.access_location)
+ _encode_general_name_preallocated(
+ backend, access_description.access_location, ad.location
+ )
ad.method = method
- ad.location = gn
res = backend._lib.sk_ACCESS_DESCRIPTION_push(aia, ad)
backend.openssl_assert(res >= 1)
@@ -385,8 +397,13 @@ def _encode_subject_key_identifier(backend, ski):
def _encode_general_name(backend, name):
+ gn = backend._lib.GENERAL_NAME_new()
+ _encode_general_name_preallocated(backend, name, gn)
+ return gn
+
+
+def _encode_general_name_preallocated(backend, name, gn):
if isinstance(name, x509.DNSName):
- gn = backend._lib.GENERAL_NAME_new()
backend.openssl_assert(gn != backend._ffi.NULL)
gn.type = backend._lib.GEN_DNS
@@ -400,32 +417,27 @@ def _encode_general_name(backend, name):
backend.openssl_assert(res == 1)
gn.d.dNSName = ia5
elif isinstance(name, x509.RegisteredID):
- gn = backend._lib.GENERAL_NAME_new()
backend.openssl_assert(gn != backend._ffi.NULL)
gn.type = backend._lib.GEN_RID
obj = backend._lib.OBJ_txt2obj(
- name.value.dotted_string.encode('ascii'), 1
+ name.value.dotted_string.encode("ascii"), 1
)
backend.openssl_assert(obj != backend._ffi.NULL)
gn.d.registeredID = obj
elif isinstance(name, x509.DirectoryName):
- gn = backend._lib.GENERAL_NAME_new()
backend.openssl_assert(gn != backend._ffi.NULL)
dir_name = _encode_name(backend, name.value)
gn.type = backend._lib.GEN_DIRNAME
gn.d.directoryName = dir_name
elif isinstance(name, x509.IPAddress):
- gn = backend._lib.GENERAL_NAME_new()
backend.openssl_assert(gn != backend._ffi.NULL)
if isinstance(name.value, ipaddress.IPv4Network):
- packed = (
- name.value.network_address.packed +
- utils.int_to_bytes(((1 << 32) - name.value.num_addresses), 4)
+ packed = name.value.network_address.packed + utils.int_to_bytes(
+ ((1 << 32) - name.value.num_addresses), 4
)
elif isinstance(name.value, ipaddress.IPv6Network):
- packed = (
- name.value.network_address.packed +
- utils.int_to_bytes((1 << 128) - name.value.num_addresses, 16)
+ packed = name.value.network_address.packed + utils.int_to_bytes(
+ (1 << 128) - name.value.num_addresses, 16
)
else:
packed = name.value.packed
@@ -433,13 +445,12 @@ def _encode_general_name(backend, name):
gn.type = backend._lib.GEN_IPADD
gn.d.iPAddress = ipaddr
elif isinstance(name, x509.OtherName):
- gn = backend._lib.GENERAL_NAME_new()
backend.openssl_assert(gn != backend._ffi.NULL)
other_name = backend._lib.OTHERNAME_new()
backend.openssl_assert(other_name != backend._ffi.NULL)
type_id = backend._lib.OBJ_txt2obj(
- name.type_id.dotted_string.encode('ascii'), 1
+ name.type_id.dotted_string.encode("ascii"), 1
)
backend.openssl_assert(type_id != backend._ffi.NULL)
data = backend._ffi.new("unsigned char[]", name.value)
@@ -456,7 +467,6 @@ def _encode_general_name(backend, name):
gn.type = backend._lib.GEN_OTHERNAME
gn.d.otherName = other_name
elif isinstance(name, x509.RFC822Name):
- gn = backend._lib.GENERAL_NAME_new()
backend.openssl_assert(gn != backend._ffi.NULL)
# ia5strings are supposed to be ITU T.50 but to allow round-tripping
# of broken certs that encode utf8 we'll encode utf8 here too.
@@ -465,7 +475,6 @@ def _encode_general_name(backend, name):
gn.type = backend._lib.GEN_EMAIL
gn.d.rfc822Name = asn1_str
elif isinstance(name, x509.UniformResourceIdentifier):
- gn = backend._lib.GENERAL_NAME_new()
backend.openssl_assert(gn != backend._ffi.NULL)
# ia5strings are supposed to be ITU T.50 but to allow round-tripping
# of broken certs that encode utf8 we'll encode utf8 here too.
@@ -474,11 +483,7 @@ def _encode_general_name(backend, name):
gn.type = backend._lib.GEN_URI
gn.d.uniformResourceIdentifier = asn1_str
else:
- raise ValueError(
- "{0} is an unknown GeneralName type".format(name)
- )
-
- return gn
+ raise ValueError("{} is an unknown GeneralName type".format(name))
def _encode_extended_key_usage(backend, extended_key_usage):
@@ -599,11 +604,21 @@ def _encode_general_subtree(backend, subtrees):
gs = backend._lib.GENERAL_SUBTREE_new()
gs.base = _encode_general_name(backend, name)
res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs)
- assert res >= 1
+ backend.openssl_assert(res >= 1)
return general_subtrees
+def _encode_precert_signed_certificate_timestamps(backend, scts):
+ sct_stack = backend._lib.sk_SCT_new_null()
+ backend.openssl_assert(sct_stack != backend._ffi.NULL)
+ sct_stack = backend._ffi.gc(sct_stack, backend._lib.sk_SCT_free)
+ for sct in scts:
+ res = backend._lib.sk_SCT_push(sct_stack, sct._sct)
+ backend.openssl_assert(res >= 1)
+ return sct_stack
+
+
def _encode_nonce(backend, nonce):
return _encode_asn1_str_gc(backend, nonce.nonce)
@@ -617,26 +632,27 @@ _EXTENSION_ENCODE_HANDLERS = {
ExtensionOID.EXTENDED_KEY_USAGE: _encode_extended_key_usage,
ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier,
ExtensionOID.CERTIFICATE_POLICIES: _encode_certificate_policies,
- ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
- _encode_authority_information_access
- ),
+ ExtensionOID.AUTHORITY_INFORMATION_ACCESS: _encode_information_access,
+ ExtensionOID.SUBJECT_INFORMATION_ACCESS: _encode_information_access,
ExtensionOID.CRL_DISTRIBUTION_POINTS: _encode_cdps_freshest_crl,
ExtensionOID.FRESHEST_CRL: _encode_cdps_freshest_crl,
ExtensionOID.INHIBIT_ANY_POLICY: _encode_inhibit_any_policy,
ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck,
ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints,
ExtensionOID.POLICY_CONSTRAINTS: _encode_policy_constraints,
+ ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: (
+ _encode_precert_signed_certificate_timestamps
+ ),
}
_CRL_EXTENSION_ENCODE_HANDLERS = {
ExtensionOID.ISSUER_ALTERNATIVE_NAME: _encode_alt_name,
ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier,
- ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
- _encode_authority_information_access
- ),
+ ExtensionOID.AUTHORITY_INFORMATION_ACCESS: _encode_information_access,
ExtensionOID.CRL_NUMBER: _encode_crl_number_delta_crl_indicator,
ExtensionOID.DELTA_CRL_INDICATOR: _encode_crl_number_delta_crl_indicator,
ExtensionOID.ISSUING_DISTRIBUTION_POINT: _encode_issuing_dist_point,
+ ExtensionOID.FRESHEST_CRL: _encode_cdps_freshest_crl,
}
_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS = {
diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py
index 549fa2bf5..764dce0ed 100644
--- a/src/cryptography/hazmat/backends/openssl/hashes.py
+++ b/src/cryptography/hazmat/backends/openssl/hashes.py
@@ -18,19 +18,21 @@ class _HashContext(object):
self._backend = backend
if ctx is None:
- ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new()
+ ctx = self._backend._lib.EVP_MD_CTX_new()
ctx = self._backend._ffi.gc(
- ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free
+ ctx, self._backend._lib.EVP_MD_CTX_free
)
evp_md = self._backend._evp_md_from_algorithm(algorithm)
if evp_md == self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
- "{0} is not a supported hash on this backend.".format(
- algorithm.name),
- _Reasons.UNSUPPORTED_HASH
+ "{} is not a supported hash on this backend.".format(
+ algorithm.name
+ ),
+ _Reasons.UNSUPPORTED_HASH,
)
- res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md,
- self._backend._ffi.NULL)
+ res = self._backend._lib.EVP_DigestInit_ex(
+ ctx, evp_md, self._backend._ffi.NULL
+ )
self._backend.openssl_assert(res != 0)
self._ctx = ctx
@@ -38,9 +40,9 @@ class _HashContext(object):
algorithm = utils.read_only_property("_algorithm")
def copy(self):
- copied_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new()
+ copied_ctx = self._backend._lib.EVP_MD_CTX_new()
copied_ctx = self._backend._ffi.gc(
- copied_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free
+ copied_ctx, self._backend._lib.EVP_MD_CTX_free
)
res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx)
self._backend.openssl_assert(res != 0)
@@ -58,21 +60,23 @@ class _HashContext(object):
# extendable output functions use a different finalize
return self._finalize_xof()
else:
- buf = self._backend._ffi.new("unsigned char[]",
- self._backend._lib.EVP_MAX_MD_SIZE)
+ buf = self._backend._ffi.new(
+ "unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE
+ )
outlen = self._backend._ffi.new("unsigned int *")
res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen)
self._backend.openssl_assert(res != 0)
self._backend.openssl_assert(
outlen[0] == self.algorithm.digest_size
)
- return self._backend._ffi.buffer(buf)[:outlen[0]]
+ return self._backend._ffi.buffer(buf)[: outlen[0]]
def _finalize_xof(self):
- buf = self._backend._ffi.new("unsigned char[]",
- self.algorithm.digest_size)
+ buf = self._backend._ffi.new(
+ "unsigned char[]", self.algorithm.digest_size
+ )
res = self._backend._lib.EVP_DigestFinalXOF(
self._ctx, buf, self.algorithm.digest_size
)
self._backend.openssl_assert(res != 0)
- return self._backend._ffi.buffer(buf)[:self.algorithm.digest_size]
+ return self._backend._ffi.buffer(buf)[: self.algorithm.digest_size]
diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py
index b23ac6498..1cc9d99fe 100644
--- a/src/cryptography/hazmat/backends/openssl/hmac.py
+++ b/src/cryptography/hazmat/backends/openssl/hmac.py
@@ -7,12 +7,13 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import (
- InvalidSignature, UnsupportedAlgorithm, _Reasons
+ InvalidSignature,
+ UnsupportedAlgorithm,
+ _Reasons,
)
-from cryptography.hazmat.primitives import constant_time, hashes, mac
+from cryptography.hazmat.primitives import constant_time, hashes
-@utils.register_interface(mac.MACContext)
@utils.register_interface(hashes.HashContext)
class _HMACContext(object):
def __init__(self, backend, key, algorithm, ctx=None):
@@ -20,17 +21,16 @@ class _HMACContext(object):
self._backend = backend
if ctx is None:
- ctx = self._backend._lib.Cryptography_HMAC_CTX_new()
+ ctx = self._backend._lib.HMAC_CTX_new()
self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
- ctx = self._backend._ffi.gc(
- ctx, self._backend._lib.Cryptography_HMAC_CTX_free
- )
+ ctx = self._backend._ffi.gc(ctx, self._backend._lib.HMAC_CTX_free)
evp_md = self._backend._evp_md_from_algorithm(algorithm)
if evp_md == self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
- "{0} is not a supported hash on this backend".format(
- algorithm.name),
- _Reasons.UNSUPPORTED_HASH
+ "{} is not a supported hash on this backend".format(
+ algorithm.name
+ ),
+ _Reasons.UNSUPPORTED_HASH,
)
key_ptr = self._backend._ffi.from_buffer(key)
res = self._backend._lib.HMAC_Init_ex(
@@ -44,10 +44,10 @@ class _HMACContext(object):
algorithm = utils.read_only_property("_algorithm")
def copy(self):
- copied_ctx = self._backend._lib.Cryptography_HMAC_CTX_new()
+ copied_ctx = self._backend._lib.HMAC_CTX_new()
self._backend.openssl_assert(copied_ctx != self._backend._ffi.NULL)
copied_ctx = self._backend._ffi.gc(
- copied_ctx, self._backend._lib.Cryptography_HMAC_CTX_free
+ copied_ctx, self._backend._lib.HMAC_CTX_free
)
res = self._backend._lib.HMAC_CTX_copy(copied_ctx, self._ctx)
self._backend.openssl_assert(res != 0)
@@ -61,13 +61,14 @@ class _HMACContext(object):
self._backend.openssl_assert(res != 0)
def finalize(self):
- buf = self._backend._ffi.new("unsigned char[]",
- self._backend._lib.EVP_MAX_MD_SIZE)
+ buf = self._backend._ffi.new(
+ "unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE
+ )
outlen = self._backend._ffi.new("unsigned int *")
res = self._backend._lib.HMAC_Final(self._ctx, buf, outlen)
self._backend.openssl_assert(res != 0)
self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size)
- return self._backend._ffi.buffer(buf)[:outlen[0]]
+ return self._backend._ffi.buffer(buf)[: outlen[0]]
def verify(self, signature):
digest = self.finalize()
diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py
index 16dbbc2ae..50c02e7a8 100644
--- a/src/cryptography/hazmat/backends/openssl/ocsp.py
+++ b/src/cryptography/hazmat/backends/openssl/ocsp.py
@@ -9,16 +9,23 @@ import functools
from cryptography import utils, x509
from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.backends.openssl.decode_asn1 import (
- _CRL_ENTRY_REASON_CODE_TO_ENUM, _OCSP_BASICRESP_EXT_PARSER,
- _OCSP_REQ_EXT_PARSER, _asn1_integer_to_int,
- _asn1_string_to_bytes, _decode_x509_name, _obj2txt,
+ _CRL_ENTRY_REASON_CODE_TO_ENUM,
+ _asn1_integer_to_int,
+ _asn1_string_to_bytes,
+ _decode_x509_name,
+ _obj2txt,
_parse_asn1_generalized_time,
)
from cryptography.hazmat.backends.openssl.x509 import _Certificate
from cryptography.hazmat.primitives import serialization
from cryptography.x509.ocsp import (
- OCSPCertStatus, OCSPRequest, OCSPResponse, OCSPResponseStatus,
- _CERT_STATUS_TO_ENUM, _OIDS_TO_HASH, _RESPONSE_STATUS_TO_ENUM,
+ OCSPCertStatus,
+ OCSPRequest,
+ OCSPResponse,
+ OCSPResponseStatus,
+ _CERT_STATUS_TO_ENUM,
+ _OIDS_TO_HASH,
+ _RESPONSE_STATUS_TO_ENUM,
)
@@ -39,8 +46,11 @@ def _requires_successful_response(func):
def _issuer_key_hash(backend, cert_id):
key_hash = backend._ffi.new("ASN1_OCTET_STRING **")
res = backend._lib.OCSP_id_get0_info(
- backend._ffi.NULL, backend._ffi.NULL,
- key_hash, backend._ffi.NULL, cert_id
+ backend._ffi.NULL,
+ backend._ffi.NULL,
+ key_hash,
+ backend._ffi.NULL,
+ cert_id,
)
backend.openssl_assert(res == 1)
backend.openssl_assert(key_hash[0] != backend._ffi.NULL)
@@ -50,8 +60,11 @@ def _issuer_key_hash(backend, cert_id):
def _issuer_name_hash(backend, cert_id):
name_hash = backend._ffi.new("ASN1_OCTET_STRING **")
res = backend._lib.OCSP_id_get0_info(
- name_hash, backend._ffi.NULL,
- backend._ffi.NULL, backend._ffi.NULL, cert_id
+ name_hash,
+ backend._ffi.NULL,
+ backend._ffi.NULL,
+ backend._ffi.NULL,
+ cert_id,
)
backend.openssl_assert(res == 1)
backend.openssl_assert(name_hash[0] != backend._ffi.NULL)
@@ -61,8 +74,7 @@ def _issuer_name_hash(backend, cert_id):
def _serial_number(backend, cert_id):
num = backend._ffi.new("ASN1_INTEGER **")
res = backend._lib.OCSP_id_get0_info(
- backend._ffi.NULL, backend._ffi.NULL,
- backend._ffi.NULL, num, cert_id
+ backend._ffi.NULL, backend._ffi.NULL, backend._ffi.NULL, num, cert_id
)
backend.openssl_assert(res == 1)
backend.openssl_assert(num[0] != backend._ffi.NULL)
@@ -72,8 +84,11 @@ def _serial_number(backend, cert_id):
def _hash_algorithm(backend, cert_id):
asn1obj = backend._ffi.new("ASN1_OBJECT **")
res = backend._lib.OCSP_id_get0_info(
- backend._ffi.NULL, asn1obj,
- backend._ffi.NULL, backend._ffi.NULL, cert_id
+ backend._ffi.NULL,
+ asn1obj,
+ backend._ffi.NULL,
+ backend._ffi.NULL,
+ cert_id,
)
backend.openssl_assert(res == 1)
backend.openssl_assert(asn1obj[0] != backend._ffi.NULL)
@@ -82,7 +97,7 @@ def _hash_algorithm(backend, cert_id):
return _OIDS_TO_HASH[oid]
except KeyError:
raise UnsupportedAlgorithm(
- "Signature algorithm OID: {0} not recognized".format(oid)
+ "Signature algorithm OID: {} not recognized".format(oid)
)
@@ -102,9 +117,13 @@ class _OCSPResponse(object):
self._basic = self._backend._ffi.gc(
basic, self._backend._lib.OCSP_BASICRESP_free
)
- self._backend.openssl_assert(
- self._backend._lib.OCSP_resp_count(self._basic) == 1
- )
+ num_resp = self._backend._lib.OCSP_resp_count(self._basic)
+ if num_resp != 1:
+ raise ValueError(
+ "OCSP response contains more than one SINGLERESP structure"
+ ", which this library does not support. "
+ "{} found".format(num_resp)
+ )
self._single = self._backend._lib.OCSP_resp_get0(self._basic, 0)
self._backend.openssl_assert(
self._single != self._backend._ffi.NULL
@@ -134,7 +153,7 @@ class _OCSPResponse(object):
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
raise UnsupportedAlgorithm(
- "Signature algorithm OID:{0} not recognized".format(oid)
+ "Signature algorithm OID:{} not recognized".format(oid)
)
@property
@@ -317,13 +336,16 @@ class _OCSPResponse(object):
@utils.cached_property
@_requires_successful_response
def extensions(self):
- return _OCSP_BASICRESP_EXT_PARSER.parse(self._backend, self._basic)
+ return self._backend._ocsp_basicresp_ext_parser.parse(self._basic)
+
+ @utils.cached_property
+ @_requires_successful_response
+ def single_extensions(self):
+ return self._backend._ocsp_singleresp_ext_parser.parse(self._single)
def public_bytes(self, encoding):
if encoding is not serialization.Encoding.DER:
- raise ValueError(
- "The only allowed encoding value is Encoding.DER"
- )
+ raise ValueError("The only allowed encoding value is Encoding.DER")
bio = self._backend._create_mem_bio_gc()
res = self._backend._lib.i2d_OCSP_RESPONSE_bio(
@@ -338,7 +360,7 @@ class _OCSPRequest(object):
def __init__(self, backend, ocsp_request):
if backend._lib.OCSP_request_onereq_count(ocsp_request) > 1:
raise NotImplementedError(
- 'OCSP request contains more than one request'
+ "OCSP request contains more than one request"
)
self._backend = backend
self._ocsp_request = ocsp_request
@@ -367,13 +389,11 @@ class _OCSPRequest(object):
@utils.cached_property
def extensions(self):
- return _OCSP_REQ_EXT_PARSER.parse(self._backend, self._ocsp_request)
+ return self._backend._ocsp_req_ext_parser.parse(self._ocsp_request)
def public_bytes(self, encoding):
if encoding is not serialization.Encoding.DER:
- raise ValueError(
- "The only allowed encoding value is Encoding.DER"
- )
+ raise ValueError("The only allowed encoding value is Encoding.DER")
bio = self._backend._create_mem_bio_gc()
res = self._backend._lib.i2d_OCSP_REQUEST_bio(bio, self._ocsp_request)
diff --git a/src/cryptography/hazmat/backends/openssl/poly1305.py b/src/cryptography/hazmat/backends/openssl/poly1305.py
new file mode 100644
index 000000000..5699918b1
--- /dev/null
+++ b/src/cryptography/hazmat/backends/openssl/poly1305.py
@@ -0,0 +1,65 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+
+from cryptography.exceptions import InvalidSignature
+from cryptography.hazmat.primitives import constant_time
+
+
+_POLY1305_TAG_SIZE = 16
+_POLY1305_KEY_SIZE = 32
+
+
+class _Poly1305Context(object):
+ def __init__(self, backend, key):
+ self._backend = backend
+
+ key_ptr = self._backend._ffi.from_buffer(key)
+ # This function copies the key into OpenSSL-owned memory so we don't
+ # need to retain it ourselves
+ evp_pkey = self._backend._lib.EVP_PKEY_new_raw_private_key(
+ self._backend._lib.NID_poly1305,
+ self._backend._ffi.NULL,
+ key_ptr,
+ len(key),
+ )
+ self._backend.openssl_assert(evp_pkey != self._backend._ffi.NULL)
+ self._evp_pkey = self._backend._ffi.gc(
+ evp_pkey, self._backend._lib.EVP_PKEY_free
+ )
+ ctx = self._backend._lib.EVP_MD_CTX_new()
+ self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
+ self._ctx = self._backend._ffi.gc(
+ ctx, self._backend._lib.EVP_MD_CTX_free
+ )
+ res = self._backend._lib.EVP_DigestSignInit(
+ self._ctx,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._evp_pkey,
+ )
+ self._backend.openssl_assert(res == 1)
+
+ def update(self, data):
+ data_ptr = self._backend._ffi.from_buffer(data)
+ res = self._backend._lib.EVP_DigestSignUpdate(
+ self._ctx, data_ptr, len(data)
+ )
+ self._backend.openssl_assert(res != 0)
+
+ def finalize(self):
+ buf = self._backend._ffi.new("unsigned char[]", _POLY1305_TAG_SIZE)
+ outlen = self._backend._ffi.new("size_t *")
+ res = self._backend._lib.EVP_DigestSignFinal(self._ctx, buf, outlen)
+ self._backend.openssl_assert(res != 0)
+ self._backend.openssl_assert(outlen[0] == _POLY1305_TAG_SIZE)
+ return self._backend._ffi.buffer(buf)[: outlen[0]]
+
+ def verify(self, tag):
+ mac = self.finalize()
+ if not constant_time.bytes_eq(mac, tag):
+ raise InvalidSignature("Value did not match computed tag.")
diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py
index 30d59bd80..82cd49c96 100644
--- a/src/cryptography/hazmat/backends/openssl/rsa.py
+++ b/src/cryptography/hazmat/backends/openssl/rsa.py
@@ -4,25 +4,34 @@
from __future__ import absolute_import, division, print_function
-import math
-
from cryptography import utils
from cryptography.exceptions import (
- InvalidSignature, UnsupportedAlgorithm, _Reasons
+ InvalidSignature,
+ UnsupportedAlgorithm,
+ _Reasons,
)
from cryptography.hazmat.backends.openssl.utils import (
- _calculate_digest_and_algorithm, _check_not_prehashed,
- _warn_sign_verify_deprecated
+ _calculate_digest_and_algorithm,
+ _check_not_prehashed,
+ _warn_sign_verify_deprecated,
)
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import (
- AsymmetricSignatureContext, AsymmetricVerificationContext, rsa
+ AsymmetricSignatureContext,
+ AsymmetricVerificationContext,
+ rsa,
)
from cryptography.hazmat.primitives.asymmetric.padding import (
- AsymmetricPadding, MGF1, OAEP, PKCS1v15, PSS, calculate_max_pss_salt_length
+ AsymmetricPadding,
+ MGF1,
+ OAEP,
+ PKCS1v15,
+ PSS,
+ calculate_max_pss_salt_length,
)
from cryptography.hazmat.primitives.asymmetric.rsa import (
- RSAPrivateKeyWithSerialization, RSAPublicKeyWithSerialization
+ RSAPrivateKeyWithSerialization,
+ RSAPublicKeyWithSerialization,
)
@@ -47,22 +56,20 @@ def _enc_dec_rsa(backend, key, data, padding):
if not isinstance(padding._mgf, MGF1):
raise UnsupportedAlgorithm(
"Only MGF1 is supported by this backend.",
- _Reasons.UNSUPPORTED_MGF
+ _Reasons.UNSUPPORTED_MGF,
)
if not backend.rsa_padding_supported(padding):
raise UnsupportedAlgorithm(
"This combination of padding and hash algorithm is not "
"supported by this backend.",
- _Reasons.UNSUPPORTED_PADDING
+ _Reasons.UNSUPPORTED_PADDING,
)
else:
raise UnsupportedAlgorithm(
- "{0} is not supported by this backend.".format(
- padding.name
- ),
- _Reasons.UNSUPPORTED_PADDING
+ "{} is not supported by this backend.".format(padding.name),
+ _Reasons.UNSUPPORTED_PADDING,
)
return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding)
@@ -76,24 +83,19 @@ def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding):
init = backend._lib.EVP_PKEY_decrypt_init
crypt = backend._lib.EVP_PKEY_decrypt
- pkey_ctx = backend._lib.EVP_PKEY_CTX_new(
- key._evp_pkey, backend._ffi.NULL
- )
+ pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL)
backend.openssl_assert(pkey_ctx != backend._ffi.NULL)
pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free)
res = init(pkey_ctx)
backend.openssl_assert(res == 1)
- res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(
- pkey_ctx, padding_enum)
+ res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum)
backend.openssl_assert(res > 0)
buf_size = backend._lib.EVP_PKEY_size(key._evp_pkey)
backend.openssl_assert(buf_size > 0)
- if (
- isinstance(padding, OAEP) and
- backend._lib.Cryptography_HAS_RSA_OAEP_MD
- ):
+ if isinstance(padding, OAEP) and backend._lib.Cryptography_HAS_RSA_OAEP_MD:
mgf1_md = backend._evp_md_non_null_from_algorithm(
- padding._mgf._algorithm)
+ padding._mgf._algorithm
+ )
res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md)
backend.openssl_assert(res > 0)
oaep_md = backend._evp_md_non_null_from_algorithm(padding._algorithm)
@@ -101,9 +103,9 @@ def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding):
backend.openssl_assert(res > 0)
if (
- isinstance(padding, OAEP) and
- padding._label is not None and
- len(padding._label) > 0
+ isinstance(padding, OAEP)
+ and padding._label is not None
+ and len(padding._label) > 0
):
# set0_rsa_oaep_label takes ownership of the char * so we need to
# copy it into some new memory
@@ -117,40 +119,19 @@ def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding):
outlen = backend._ffi.new("size_t *", buf_size)
buf = backend._ffi.new("unsigned char[]", buf_size)
+ # Everything from this line onwards is written with the goal of being as
+ # constant-time as is practical given the constraints of Python and our
+ # API. See Bleichenbacher's '98 attack on RSA, and its many many variants.
+ # As such, you should not attempt to change this (particularly to "clean it
+ # up") without understanding why it was written this way (see
+ # Chesterton's Fence), and without measuring to verify you have not
+ # introduced observable time differences.
res = crypt(pkey_ctx, buf, outlen, data, len(data))
+ resbuf = backend._ffi.buffer(buf)[: outlen[0]]
+ backend._lib.ERR_clear_error()
if res <= 0:
- _handle_rsa_enc_dec_error(backend, key)
-
- return backend._ffi.buffer(buf)[:outlen[0]]
-
-
-def _handle_rsa_enc_dec_error(backend, key):
- errors = backend._consume_errors()
- backend.openssl_assert(errors)
- backend.openssl_assert(errors[0].lib == backend._lib.ERR_LIB_RSA)
- if isinstance(key, _RSAPublicKey):
- backend.openssl_assert(
- errors[0].reason == backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE
- )
- raise ValueError(
- "Data too long for key size. Encrypt less data or use a "
- "larger key size."
- )
- else:
- decoding_errors = [
- backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01,
- backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_02,
- backend._lib.RSA_R_OAEP_DECODING_ERROR,
- # Though this error looks similar to the
- # RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE, this occurs on decrypts,
- # rather than on encrypts
- backend._lib.RSA_R_DATA_TOO_LARGE_FOR_MODULUS,
- ]
- if backend._lib.Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR:
- decoding_errors.append(backend._lib.RSA_R_PKCS_DECODING_ERROR)
-
- backend.openssl_assert(errors[0].reason in decoding_errors)
- raise ValueError("Decryption failed.")
+ raise ValueError("Encryption/decryption failed.")
+ return resbuf
def _rsa_sig_determine_padding(backend, key, padding, algorithm):
@@ -161,49 +142,68 @@ def _rsa_sig_determine_padding(backend, key, padding, algorithm):
backend.openssl_assert(pkey_size > 0)
if isinstance(padding, PKCS1v15):
+ # Hash algorithm is ignored for PKCS1v15-padding, may be None.
padding_enum = backend._lib.RSA_PKCS1_PADDING
elif isinstance(padding, PSS):
if not isinstance(padding._mgf, MGF1):
raise UnsupportedAlgorithm(
"Only MGF1 is supported by this backend.",
- _Reasons.UNSUPPORTED_MGF
+ _Reasons.UNSUPPORTED_MGF,
)
+ # PSS padding requires a hash algorithm
+ if not isinstance(algorithm, hashes.HashAlgorithm):
+ raise TypeError("Expected instance of hashes.HashAlgorithm.")
+
# Size of key in bytes - 2 is the maximum
# PSS signature length (salt length is checked later)
if pkey_size - algorithm.digest_size - 2 < 0:
- raise ValueError("Digest too large for key size. Use a larger "
- "key or different digest.")
+ raise ValueError(
+ "Digest too large for key size. Use a larger "
+ "key or different digest."
+ )
padding_enum = backend._lib.RSA_PKCS1_PSS_PADDING
else:
raise UnsupportedAlgorithm(
- "{0} is not supported by this backend.".format(padding.name),
- _Reasons.UNSUPPORTED_PADDING
+ "{} is not supported by this backend.".format(padding.name),
+ _Reasons.UNSUPPORTED_PADDING,
)
return padding_enum
-def _rsa_sig_setup(backend, padding, algorithm, key, data, init_func):
+# Hash algorithm can be absent (None) to initialize the context without setting
+# any message digest algorithm. This is currently only valid for the PKCS1v15
+# padding type, where it means that the signature data is encoded/decoded
+# as provided, without being wrapped in a DigestInfo structure.
+def _rsa_sig_setup(backend, padding, algorithm, key, init_func):
padding_enum = _rsa_sig_determine_padding(backend, key, padding, algorithm)
- evp_md = backend._evp_md_non_null_from_algorithm(algorithm)
pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL)
backend.openssl_assert(pkey_ctx != backend._ffi.NULL)
pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free)
res = init_func(pkey_ctx)
backend.openssl_assert(res == 1)
- res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md)
- if res == 0:
+ if algorithm is not None:
+ evp_md = backend._evp_md_non_null_from_algorithm(algorithm)
+ res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md)
+ if res == 0:
+ backend._consume_errors()
+ raise UnsupportedAlgorithm(
+ "{} is not supported by this backend for RSA signing.".format(
+ algorithm.name
+ ),
+ _Reasons.UNSUPPORTED_HASH,
+ )
+ res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum)
+ if res <= 0:
backend._consume_errors()
raise UnsupportedAlgorithm(
- "{0} is not supported by this backend for RSA signing.".format(
- algorithm.name
+ "{} is not supported for the RSA signature operation.".format(
+ padding.name
),
- _Reasons.UNSUPPORTED_HASH
+ _Reasons.UNSUPPORTED_PADDING,
)
- res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum)
- backend.openssl_assert(res > 0)
if isinstance(padding, PSS):
res = backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
pkey_ctx, _get_rsa_pss_salt_length(padding, key, algorithm)
@@ -211,7 +211,8 @@ def _rsa_sig_setup(backend, padding, algorithm, key, data, init_func):
backend.openssl_assert(res > 0)
mgf1_md = backend._evp_md_non_null_from_algorithm(
- padding._mgf._algorithm)
+ padding._mgf._algorithm
+ )
res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md)
backend.openssl_assert(res > 0)
@@ -220,45 +221,37 @@ def _rsa_sig_setup(backend, padding, algorithm, key, data, init_func):
def _rsa_sig_sign(backend, padding, algorithm, private_key, data):
pkey_ctx = _rsa_sig_setup(
- backend, padding, algorithm, private_key, data,
- backend._lib.EVP_PKEY_sign_init
+ backend,
+ padding,
+ algorithm,
+ private_key,
+ backend._lib.EVP_PKEY_sign_init,
)
buflen = backend._ffi.new("size_t *")
res = backend._lib.EVP_PKEY_sign(
- pkey_ctx,
- backend._ffi.NULL,
- buflen,
- data,
- len(data)
+ pkey_ctx, backend._ffi.NULL, buflen, data, len(data)
)
backend.openssl_assert(res == 1)
buf = backend._ffi.new("unsigned char[]", buflen[0])
- res = backend._lib.EVP_PKEY_sign(
- pkey_ctx, buf, buflen, data, len(data))
+ res = backend._lib.EVP_PKEY_sign(pkey_ctx, buf, buflen, data, len(data))
if res != 1:
- errors = backend._consume_errors()
- backend.openssl_assert(errors[0].lib == backend._lib.ERR_LIB_RSA)
- if (
- errors[0].reason ==
- backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE
- ):
- reason = ("Salt length too long for key size. Try using "
- "MAX_LENGTH instead.")
- else:
- backend.openssl_assert(
- errors[0].reason ==
- backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY
- )
- reason = "Digest too large for key size. Use a larger key."
- raise ValueError(reason)
+ errors = backend._consume_errors_with_text()
+ raise ValueError(
+ "Digest or salt length too long for key size. Use a larger key "
+ "or shorter salt length if you are specifying a PSS salt",
+ errors,
+ )
return backend._ffi.buffer(buf)[:]
def _rsa_sig_verify(backend, padding, algorithm, public_key, signature, data):
pkey_ctx = _rsa_sig_setup(
- backend, padding, algorithm, public_key, data,
- backend._lib.EVP_PKEY_verify_init
+ backend,
+ padding,
+ algorithm,
+ public_key,
+ backend._lib.EVP_PKEY_verify_init,
)
res = backend._lib.EVP_PKEY_verify(
pkey_ctx, signature, len(signature), data, len(data)
@@ -272,6 +265,36 @@ def _rsa_sig_verify(backend, padding, algorithm, public_key, signature, data):
raise InvalidSignature
+def _rsa_sig_recover(backend, padding, algorithm, public_key, signature):
+ pkey_ctx = _rsa_sig_setup(
+ backend,
+ padding,
+ algorithm,
+ public_key,
+ backend._lib.EVP_PKEY_verify_recover_init,
+ )
+
+ # Attempt to keep the rest of the code in this function as constant/time
+ # as possible. See the comment in _enc_dec_rsa_pkey_ctx. Note that the
+ # outlen parameter is used even though its value may be undefined in the
+ # error case. Due to the tolerant nature of Python slicing this does not
+ # trigger any exceptions.
+ maxlen = backend._lib.EVP_PKEY_size(public_key._evp_pkey)
+ backend.openssl_assert(maxlen > 0)
+ buf = backend._ffi.new("unsigned char[]", maxlen)
+ buflen = backend._ffi.new("size_t *", maxlen)
+ res = backend._lib.EVP_PKEY_verify_recover(
+ pkey_ctx, buf, buflen, signature, len(signature)
+ )
+ resbuf = backend._ffi.buffer(buf)[: buflen[0]]
+ backend._lib.ERR_clear_error()
+ # Assume that all parameter errors are handled during the setup phase and
+ # any error here is due to invalid signature.
+ if res != 1:
+ raise InvalidSignature
+ return resbuf
+
+
@utils.register_interface(AsymmetricSignatureContext)
class _RSASignatureContext(object):
def __init__(self, backend, private_key, padding, algorithm):
@@ -295,7 +318,7 @@ class _RSASignatureContext(object):
self._padding,
self._algorithm,
self._private_key,
- self._hash_ctx.finalize()
+ self._hash_ctx.finalize(),
)
@@ -325,21 +348,33 @@ class _RSAVerificationContext(object):
self._algorithm,
self._public_key,
self._signature,
- self._hash_ctx.finalize()
+ self._hash_ctx.finalize(),
)
@utils.register_interface(RSAPrivateKeyWithSerialization)
class _RSAPrivateKey(object):
def __init__(self, backend, rsa_cdata, evp_pkey):
+ res = backend._lib.RSA_check_key(rsa_cdata)
+ if res != 1:
+ errors = backend._consume_errors_with_text()
+ raise ValueError("Invalid private key", errors)
+
+ # Blinding is on by default in many versions of OpenSSL, but let's
+ # just be conservative here.
+ res = backend._lib.RSA_blinding_on(rsa_cdata, backend._ffi.NULL)
+ backend.openssl_assert(res == 1)
+
self._backend = backend
self._rsa_cdata = rsa_cdata
self._evp_pkey = evp_pkey
n = self._backend._ffi.new("BIGNUM **")
self._backend._lib.RSA_get0_key(
- self._rsa_cdata, n, self._backend._ffi.NULL,
- self._backend._ffi.NULL
+ self._rsa_cdata,
+ n,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
)
self._backend.openssl_assert(n[0] != self._backend._ffi.NULL)
self._key_size = self._backend._lib.BN_num_bits(n[0])
@@ -352,7 +387,7 @@ class _RSAPrivateKey(object):
return _RSASignatureContext(self._backend, self, padding, algorithm)
def decrypt(self, ciphertext, padding):
- key_size_bytes = int(math.ceil(self.key_size / 8.0))
+ key_size_bytes = (self.key_size + 7) // 8
if key_size_bytes != len(ciphertext):
raise ValueError("Ciphertext length must be equal to key size.")
@@ -362,8 +397,6 @@ class _RSAPrivateKey(object):
ctx = self._backend._lib.RSAPublicKey_dup(self._rsa_cdata)
self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
ctx = self._backend._ffi.gc(ctx, self._backend._lib.RSA_free)
- res = self._backend._lib.RSA_blinding_on(ctx, self._backend._ffi.NULL)
- self._backend.openssl_assert(res == 1)
evp_pkey = self._backend._rsa_cdata_to_evp_pkey(ctx)
return _RSAPublicKey(self._backend, ctx, evp_pkey)
@@ -399,7 +432,7 @@ class _RSAPrivateKey(object):
public_numbers=rsa.RSAPublicNumbers(
e=self._backend._bn_to_int(e[0]),
n=self._backend._bn_to_int(n[0]),
- )
+ ),
)
def private_bytes(self, encoding, format, encryption_algorithm):
@@ -407,8 +440,9 @@ class _RSAPrivateKey(object):
encoding,
format,
encryption_algorithm,
+ self,
self._evp_pkey,
- self._rsa_cdata
+ self._rsa_cdata,
)
def sign(self, data, padding, algorithm):
@@ -427,8 +461,10 @@ class _RSAPublicKey(object):
n = self._backend._ffi.new("BIGNUM **")
self._backend._lib.RSA_get0_key(
- self._rsa_cdata, n, self._backend._ffi.NULL,
- self._backend._ffi.NULL
+ self._rsa_cdata,
+ n,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
)
self._backend.openssl_assert(n[0] != self._backend._ffi.NULL)
self._key_size = self._backend._lib.BN_num_bits(n[0])
@@ -462,11 +498,7 @@ class _RSAPublicKey(object):
def public_bytes(self, encoding, format):
return self._backend._public_key_bytes(
- encoding,
- format,
- self,
- self._evp_pkey,
- self._rsa_cdata
+ encoding, format, self, self._evp_pkey, self._rsa_cdata
)
def verify(self, signature, data, padding, algorithm):
@@ -476,3 +508,9 @@ class _RSAPublicKey(object):
return _rsa_sig_verify(
self._backend, padding, algorithm, self, signature, data
)
+
+ def recover_data_from_signature(self, signature, padding, algorithm):
+ _check_not_prehashed(algorithm)
+ return _rsa_sig_recover(
+ self._backend, padding, algorithm, self, signature
+ )
diff --git a/src/cryptography/hazmat/backends/openssl/utils.py b/src/cryptography/hazmat/backends/openssl/utils.py
index 363f3d2c2..3d697d1fb 100644
--- a/src/cryptography/hazmat/backends/openssl/utils.py
+++ b/src/cryptography/hazmat/backends/openssl/utils.py
@@ -17,9 +17,7 @@ def _evp_pkey_derive(backend, evp_pkey, peer_public_key):
ctx = backend._ffi.gc(ctx, backend._lib.EVP_PKEY_CTX_free)
res = backend._lib.EVP_PKEY_derive_init(ctx)
backend.openssl_assert(res == 1)
- res = backend._lib.EVP_PKEY_derive_set_peer(
- ctx, peer_public_key._evp_pkey
- )
+ res = backend._lib.EVP_PKEY_derive_set_peer(ctx, peer_public_key._evp_pkey)
backend.openssl_assert(res == 1)
keylen = backend._ffi.new("size_t *")
res = backend._lib.EVP_PKEY_derive(ctx, backend._ffi.NULL, keylen)
@@ -28,9 +26,7 @@ def _evp_pkey_derive(backend, evp_pkey, peer_public_key):
buf = backend._ffi.new("unsigned char[]", keylen[0])
res = backend._lib.EVP_PKEY_derive(ctx, buf, keylen)
if res != 1:
- raise ValueError(
- "Null shared key derived from public/private pair."
- )
+ raise ValueError("Null shared key derived from public/private pair.")
return backend._ffi.buffer(buf, keylen[0])[:]
@@ -56,7 +52,8 @@ def _check_not_prehashed(signature_algorithm):
if isinstance(signature_algorithm, Prehashed):
raise TypeError(
"Prehashed is only supported in the sign and verify methods. "
- "It cannot be used with signer or verifier."
+ "It cannot be used with signer, verifier or "
+ "recover_data_from_signature."
)
@@ -64,6 +61,6 @@ def _warn_sign_verify_deprecated():
warnings.warn(
"signer and verifier have been deprecated. Please use sign "
"and verify instead.",
- utils.PersistentlyDeprecated,
- stacklevel=3
+ utils.PersistentlyDeprecated2017,
+ stacklevel=3,
)
diff --git a/src/cryptography/hazmat/backends/openssl/x25519.py b/src/cryptography/hazmat/backends/openssl/x25519.py
index 914f59413..4971c5481 100644
--- a/src/cryptography/hazmat/backends/openssl/x25519.py
+++ b/src/cryptography/hazmat/backends/openssl/x25519.py
@@ -4,13 +4,12 @@
from __future__ import absolute_import, division, print_function
-import warnings
-
from cryptography import utils
from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.x25519 import (
- X25519PrivateKey, X25519PublicKey
+ X25519PrivateKey,
+ X25519PublicKey,
)
@@ -23,26 +22,14 @@ class _X25519PublicKey(object):
self._backend = backend
self._evp_pkey = evp_pkey
- def public_bytes(self, encoding=None, format=None):
- if encoding is None or format is None:
- if encoding is not None or format is not None:
- raise ValueError("Both encoding and format are required")
- else:
- warnings.warn(
- "public_bytes now requires encoding and format arguments. "
- "Support for calling without arguments will be removed in "
- "cryptography 2.7",
- utils.DeprecatedIn25,
- )
- encoding = serialization.Encoding.Raw
- format = serialization.PublicFormat.Raw
+ def public_bytes(self, encoding, format):
if (
- encoding is serialization.Encoding.Raw or
- format is serialization.PublicFormat.Raw
+ encoding is serialization.Encoding.Raw
+ or format is serialization.PublicFormat.Raw
):
if (
- encoding is not serialization.Encoding.Raw or
- format is not serialization.PublicFormat.Raw
+ encoding is not serialization.Encoding.Raw
+ or format is not serialization.PublicFormat.Raw
):
raise ValueError(
"When using Raw both encoding and format must be Raw"
@@ -50,15 +37,6 @@ class _X25519PublicKey(object):
return self._raw_public_bytes()
- if (
- encoding in serialization._PEM_DER and
- format is not serialization.PublicFormat.SubjectPublicKeyInfo
- ):
- raise ValueError(
- "format must be SubjectPublicKeyInfo when encoding is PEM or "
- "DER"
- )
-
return self._backend._public_key_bytes(
encoding, format, self, self._evp_pkey, None
)
@@ -99,37 +77,29 @@ class _X25519PrivateKey(object):
if not isinstance(peer_public_key, X25519PublicKey):
raise TypeError("peer_public_key must be X25519PublicKey.")
- return _evp_pkey_derive(
- self._backend, self._evp_pkey, peer_public_key
- )
+ return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key)
def private_bytes(self, encoding, format, encryption_algorithm):
if (
- encoding is serialization.Encoding.Raw or
- format is serialization.PublicFormat.Raw
+ encoding is serialization.Encoding.Raw
+ or format is serialization.PublicFormat.Raw
):
if (
- format is not serialization.PrivateFormat.Raw or
- encoding is not serialization.Encoding.Raw or not
- isinstance(encryption_algorithm, serialization.NoEncryption)
+ format is not serialization.PrivateFormat.Raw
+ or encoding is not serialization.Encoding.Raw
+ or not isinstance(
+ encryption_algorithm, serialization.NoEncryption
+ )
):
raise ValueError(
"When using Raw both encoding and format must be Raw "
- "and encryption_algorithm must be NoEncryption"
+ "and encryption_algorithm must be NoEncryption()"
)
return self._raw_private_bytes()
- if (
- encoding in serialization._PEM_DER and
- format is not serialization.PrivateFormat.PKCS8
- ):
- raise ValueError(
- "format must be PKCS8 when encoding is PEM or DER"
- )
-
return self._backend._private_key_bytes(
- encoding, format, encryption_algorithm, self._evp_pkey, None
+ encoding, format, encryption_algorithm, self, self._evp_pkey, None
)
def _raw_private_bytes(self):
@@ -139,9 +109,13 @@ class _X25519PrivateKey(object):
# using the last 32 bytes, which is the key itself.
bio = self._backend._create_mem_bio_gc()
res = self._backend._lib.i2d_PKCS8PrivateKey_bio(
- bio, self._evp_pkey,
- self._backend._ffi.NULL, self._backend._ffi.NULL,
- 0, self._backend._ffi.NULL, self._backend._ffi.NULL
+ bio,
+ self._evp_pkey,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ 0,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
)
self._backend.openssl_assert(res == 1)
pkcs8 = self._backend._read_mem_bio(bio)
diff --git a/src/cryptography/hazmat/backends/openssl/x448.py b/src/cryptography/hazmat/backends/openssl/x448.py
index 13e4ce15e..7ebcdf84b 100644
--- a/src/cryptography/hazmat/backends/openssl/x448.py
+++ b/src/cryptography/hazmat/backends/openssl/x448.py
@@ -8,7 +8,8 @@ from cryptography import utils
from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.x448 import (
- X448PrivateKey, X448PublicKey
+ X448PrivateKey,
+ X448PublicKey,
)
_X448_KEY_SIZE = 56
@@ -22,12 +23,12 @@ class _X448PublicKey(object):
def public_bytes(self, encoding, format):
if (
- encoding is serialization.Encoding.Raw or
- format is serialization.PublicFormat.Raw
+ encoding is serialization.Encoding.Raw
+ or format is serialization.PublicFormat.Raw
):
if (
- encoding is not serialization.Encoding.Raw or
- format is not serialization.PublicFormat.Raw
+ encoding is not serialization.Encoding.Raw
+ or format is not serialization.PublicFormat.Raw
):
raise ValueError(
"When using Raw both encoding and format must be Raw"
@@ -35,15 +36,6 @@ class _X448PublicKey(object):
return self._raw_public_bytes()
- if (
- encoding in serialization._PEM_DER and
- format is not serialization.PublicFormat.SubjectPublicKeyInfo
- ):
- raise ValueError(
- "format must be SubjectPublicKeyInfo when encoding is PEM or "
- "DER"
- )
-
return self._backend._public_key_bytes(
encoding, format, self, self._evp_pkey, None
)
@@ -79,37 +71,29 @@ class _X448PrivateKey(object):
if not isinstance(peer_public_key, X448PublicKey):
raise TypeError("peer_public_key must be X448PublicKey.")
- return _evp_pkey_derive(
- self._backend, self._evp_pkey, peer_public_key
- )
+ return _evp_pkey_derive(self._backend, self._evp_pkey, peer_public_key)
def private_bytes(self, encoding, format, encryption_algorithm):
if (
- encoding is serialization.Encoding.Raw or
- format is serialization.PublicFormat.Raw
+ encoding is serialization.Encoding.Raw
+ or format is serialization.PublicFormat.Raw
):
if (
- format is not serialization.PrivateFormat.Raw or
- encoding is not serialization.Encoding.Raw or not
- isinstance(encryption_algorithm, serialization.NoEncryption)
+ format is not serialization.PrivateFormat.Raw
+ or encoding is not serialization.Encoding.Raw
+ or not isinstance(
+ encryption_algorithm, serialization.NoEncryption
+ )
):
raise ValueError(
"When using Raw both encoding and format must be Raw "
- "and encryption_algorithm must be NoEncryption"
+ "and encryption_algorithm must be NoEncryption()"
)
return self._raw_private_bytes()
- if (
- encoding in serialization._PEM_DER and
- format is not serialization.PrivateFormat.PKCS8
- ):
- raise ValueError(
- "format must be PKCS8 when encoding is PEM or DER"
- )
-
return self._backend._private_key_bytes(
- encoding, format, encryption_algorithm, self._evp_pkey, None
+ encoding, format, encryption_algorithm, self, self._evp_pkey, None
)
def _raw_private_bytes(self):
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index ac1838c6d..4d0dac764 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -6,31 +6,43 @@ from __future__ import absolute_import, division, print_function
import datetime
import operator
-import warnings
from cryptography import utils, x509
from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.backends.openssl.decode_asn1 import (
- _CERTIFICATE_EXTENSION_PARSER, _CERTIFICATE_EXTENSION_PARSER_NO_SCT,
- _CRL_EXTENSION_PARSER, _CSR_EXTENSION_PARSER,
- _REVOKED_CERTIFICATE_EXTENSION_PARSER, _asn1_integer_to_int,
- _asn1_string_to_bytes, _decode_x509_name, _obj2txt, _parse_asn1_time
+ _asn1_integer_to_int,
+ _asn1_string_to_bytes,
+ _decode_x509_name,
+ _obj2txt,
+ _parse_asn1_time,
)
from cryptography.hazmat.backends.openssl.encode_asn1 import (
- _encode_asn1_int_gc
+ _encode_asn1_int_gc,
+ _txt2obj_gc,
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
+from cryptography.x509.name import _ASN1Type
@utils.register_interface(x509.Certificate)
class _Certificate(object):
- def __init__(self, backend, x509):
+ def __init__(self, backend, x509_cert):
self._backend = backend
- self._x509 = x509
+ self._x509 = x509_cert
+
+ version = self._backend._lib.X509_get_version(self._x509)
+ if version == 0:
+ self._version = x509.Version.v1
+ elif version == 2:
+ self._version = x509.Version.v3
+ else:
+ raise x509.InvalidVersion(
+ "{} is not a valid X509 version".format(version), version
+ )
def __repr__(self):
- return "<Certificate(subject={0}, ...)>".format(self.subject)
+ return "<Certificate(subject={}, ...)>".format(self.subject)
def __eq__(self, other):
if not isinstance(other, x509.Certificate):
@@ -45,31 +57,15 @@ class _Certificate(object):
def __hash__(self):
return hash(self.public_bytes(serialization.Encoding.DER))
+ def __deepcopy__(self, memo):
+ return self
+
def fingerprint(self, algorithm):
h = hashes.Hash(algorithm, self._backend)
h.update(self.public_bytes(serialization.Encoding.DER))
return h.finalize()
- @property
- def version(self):
- version = self._backend._lib.X509_get_version(self._x509)
- if version == 0:
- return x509.Version.v1
- elif version == 2:
- return x509.Version.v3
- else:
- raise x509.InvalidVersion(
- "{0} is not a valid X509 version".format(version), version
- )
-
- @property
- def serial(self):
- warnings.warn(
- "Certificate serial is deprecated, use serial_number instead.",
- utils.PersistentlyDeprecated,
- stacklevel=2
- )
- return self.serial_number
+ version = utils.read_only_property("_version")
@property
def serial_number(self):
@@ -90,12 +86,12 @@ class _Certificate(object):
@property
def not_valid_before(self):
- asn1_time = self._backend._lib.X509_get_notBefore(self._x509)
+ asn1_time = self._backend._lib.X509_getm_notBefore(self._x509)
return _parse_asn1_time(self._backend, asn1_time)
@property
def not_valid_after(self):
- asn1_time = self._backend._lib.X509_get_notAfter(self._x509)
+ asn1_time = self._backend._lib.X509_getm_notAfter(self._x509)
return _parse_asn1_time(self._backend, asn1_time)
@property
@@ -117,7 +113,7 @@ class _Certificate(object):
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
raise UnsupportedAlgorithm(
- "Signature algorithm OID:{0} not recognized".format(oid)
+ "Signature algorithm OID:{} not recognized".format(oid)
)
@property
@@ -132,14 +128,7 @@ class _Certificate(object):
@utils.cached_property
def extensions(self):
- if self._backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER:
- return _CERTIFICATE_EXTENSION_PARSER.parse(
- self._backend, self._x509
- )
- else:
- return _CERTIFICATE_EXTENSION_PARSER_NO_SCT.parse(
- self._backend, self._x509
- )
+ return self._backend._certificate_extension_parser.parse(self._x509)
@property
def signature(self):
@@ -201,13 +190,13 @@ class _RevokedCertificate(object):
self._backend,
self._backend._lib.X509_REVOKED_get0_revocationDate(
self._x509_revoked
- )
+ ),
)
@utils.cached_property
def extensions(self):
- return _REVOKED_CERTIFICATE_EXTENSION_PARSER.parse(
- self._backend, self._x509_revoked
+ return self._backend._revoked_cert_extension_parser.parse(
+ self._x509_revoked
)
@@ -230,9 +219,7 @@ class _CertificateRevocationList(object):
def fingerprint(self, algorithm):
h = hashes.Hash(algorithm, self._backend)
bio = self._backend._create_mem_bio_gc()
- res = self._backend._lib.i2d_X509_CRL_bio(
- bio, self._x509_crl
- )
+ res = self._backend._lib.i2d_X509_CRL_bio(bio, self._x509_crl)
self._backend.openssl_assert(res == 1)
der = self._backend._read_mem_bio(bio)
h.update(der)
@@ -257,9 +244,7 @@ class _CertificateRevocationList(object):
if res == 0:
return None
else:
- self._backend.openssl_assert(
- revoked[0] != self._backend._ffi.NULL
- )
+ self._backend.openssl_assert(revoked[0] != self._backend._ffi.NULL)
return _RevokedCertificate(
self._backend, self._sorted_crl, revoked[0]
)
@@ -271,7 +256,7 @@ class _CertificateRevocationList(object):
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
raise UnsupportedAlgorithm(
- "Signature algorithm OID:{0} not recognized".format(oid)
+ "Signature algorithm OID:{} not recognized".format(oid)
)
@property
@@ -366,13 +351,17 @@ class _CertificateRevocationList(object):
@utils.cached_property
def extensions(self):
- return _CRL_EXTENSION_PARSER.parse(self._backend, self._x509_crl)
+ return self._backend._crl_extension_parser.parse(self._x509_crl)
def is_signature_valid(self, public_key):
- if not isinstance(public_key, (dsa.DSAPublicKey, rsa.RSAPublicKey,
- ec.EllipticCurvePublicKey)):
- raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,'
- ' or EllipticCurvePublicKey.')
+ if not isinstance(
+ public_key,
+ (dsa.DSAPublicKey, rsa.RSAPublicKey, ec.EllipticCurvePublicKey),
+ ):
+ raise TypeError(
+ "Expecting one of DSAPublicKey, RSAPublicKey,"
+ " or EllipticCurvePublicKey."
+ )
res = self._backend._lib.X509_CRL_verify(
self._x509_crl, public_key._evp_pkey
)
@@ -423,7 +412,7 @@ class _CertificateSigningRequest(object):
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
raise UnsupportedAlgorithm(
- "Signature algorithm OID:{0} not recognized".format(oid)
+ "Signature algorithm OID:{} not recognized".format(oid)
)
@property
@@ -442,12 +431,13 @@ class _CertificateSigningRequest(object):
x509_exts = self._backend._ffi.gc(
x509_exts,
lambda x: self._backend._lib.sk_X509_EXTENSION_pop_free(
- x, self._backend._ffi.addressof(
+ x,
+ self._backend._ffi.addressof(
self._backend._lib._original_lib, "X509_EXTENSION_free"
- )
- )
+ ),
+ ),
)
- return _CSR_EXTENSION_PARSER.parse(self._backend, x509_exts)
+ return self._backend._csr_extension_parser.parse(x509_exts)
def public_bytes(self, encoding):
bio = self._backend._create_mem_bio_gc()
@@ -495,6 +485,47 @@ class _CertificateSigningRequest(object):
return True
+ def get_attribute_for_oid(self, oid):
+ obj = _txt2obj_gc(self._backend, oid.dotted_string)
+ pos = self._backend._lib.X509_REQ_get_attr_by_OBJ(
+ self._x509_req, obj, -1
+ )
+ if pos == -1:
+ raise x509.AttributeNotFound(
+ "No {} attribute was found".format(oid), oid
+ )
+
+ attr = self._backend._lib.X509_REQ_get_attr(self._x509_req, pos)
+ self._backend.openssl_assert(attr != self._backend._ffi.NULL)
+ # We don't support multiple valued attributes for now.
+ self._backend.openssl_assert(
+ self._backend._lib.X509_ATTRIBUTE_count(attr) == 1
+ )
+ asn1_type = self._backend._lib.X509_ATTRIBUTE_get0_type(attr, 0)
+ self._backend.openssl_assert(asn1_type != self._backend._ffi.NULL)
+ # We need this to ensure that our C type cast is safe.
+ # Also this should always be a sane string type, but we'll see if
+ # that is true in the real world...
+ if asn1_type.type not in (
+ _ASN1Type.UTF8String.value,
+ _ASN1Type.PrintableString.value,
+ _ASN1Type.IA5String.value,
+ ):
+ raise ValueError(
+ "OID {} has a disallowed ASN.1 type: {}".format(
+ oid, asn1_type.type
+ )
+ )
+
+ data = self._backend._lib.X509_ATTRIBUTE_get0_data(
+ attr, 0, asn1_type.type, self._backend._ffi.NULL
+ )
+ self._backend.openssl_assert(data != self._backend._ffi.NULL)
+ # This cast is safe iff we assert on the type above to ensure
+ # that it is always a type of ASN1_STRING
+ data = self._backend._ffi.cast("ASN1_STRING *", data)
+ return _asn1_string_to_bytes(self._backend, data)
+
@utils.register_interface(
x509.certificate_transparency.SignedCertificateTimestamp
@@ -523,9 +554,9 @@ class _SignedCertificateTimestamp(object):
def timestamp(self):
timestamp = self._backend._lib.SCT_get_timestamp(self._sct)
milliseconds = timestamp % 1000
- return datetime.datetime.utcfromtimestamp(
- timestamp // 1000
- ).replace(microsecond=milliseconds * 1000)
+ return datetime.datetime.utcfromtimestamp(timestamp // 1000).replace(
+ microsecond=milliseconds * 1000
+ )
@property
def entry_type(self):
diff --git a/src/cryptography/hazmat/bindings/_constant_time.so b/src/cryptography/hazmat/bindings/_constant_time.so
deleted file mode 100644
index 6a3435955..000000000
--- a/src/cryptography/hazmat/bindings/_constant_time.so
+++ /dev/null
Binary files differ
diff --git a/src/cryptography/hazmat/bindings/_openssl.so b/src/cryptography/hazmat/bindings/_openssl.so
index d896a793b..6551c6a15 100644..100755
--- a/src/cryptography/hazmat/bindings/_openssl.so
+++ b/src/cryptography/hazmat/bindings/_openssl.so
Binary files differ
diff --git a/src/cryptography/hazmat/bindings/_padding.so b/src/cryptography/hazmat/bindings/_padding.so
index a27d09e58..5cdc438f0 100644..100755
--- a/src/cryptography/hazmat/bindings/_padding.so
+++ b/src/cryptography/hazmat/bindings/_padding.so
Binary files differ
diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py
index c0238dcc2..ca50fed13 100644
--- a/src/cryptography/hazmat/bindings/openssl/_conditional.py
+++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py
@@ -13,24 +13,6 @@ def cryptography_has_ec2m():
]
-def cryptography_has_ec_1_0_2():
- return [
- "EC_curve_nid2nist",
- ]
-
-
-def cryptography_has_set_ecdh_auto():
- return [
- "SSL_CTX_set_ecdh_auto",
- ]
-
-
-def cryptography_has_rsa_r_pkcs_decoding_error():
- return [
- "RSA_R_PKCS_DECODING_ERROR"
- ]
-
-
def cryptography_has_rsa_oaep_md():
return [
"EVP_PKEY_CTX_set_rsa_oaep_md",
@@ -51,78 +33,22 @@ def cryptography_has_ssl3_method():
]
-def cryptography_has_alpn():
- return [
- "SSL_CTX_set_alpn_protos",
- "SSL_set_alpn_protos",
- "SSL_CTX_set_alpn_select_cb",
- "SSL_get0_alpn_selected",
- ]
-
-
-def cryptography_has_compression():
- return [
- "SSL_get_current_compression",
- "SSL_get_current_expansion",
- "SSL_COMP_get_name",
- ]
-
-
-def cryptography_has_get_server_tmp_key():
- return [
- "SSL_get_server_tmp_key",
- ]
-
-
-def cryptography_has_102_verification_error_codes():
- return [
- 'X509_V_ERR_SUITE_B_INVALID_VERSION',
- 'X509_V_ERR_SUITE_B_INVALID_ALGORITHM',
- 'X509_V_ERR_SUITE_B_INVALID_CURVE',
- 'X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM',
- 'X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED',
- 'X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256',
- 'X509_V_ERR_HOSTNAME_MISMATCH',
- 'X509_V_ERR_EMAIL_MISMATCH',
- 'X509_V_ERR_IP_ADDRESS_MISMATCH'
- ]
-
-
-def cryptography_has_102_verification_params():
+def cryptography_has_102_verification():
return [
+ "X509_V_ERR_SUITE_B_INVALID_VERSION",
+ "X509_V_ERR_SUITE_B_INVALID_ALGORITHM",
+ "X509_V_ERR_SUITE_B_INVALID_CURVE",
+ "X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM",
+ "X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED",
+ "X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256",
"X509_V_FLAG_SUITEB_128_LOS_ONLY",
"X509_V_FLAG_SUITEB_192_LOS",
"X509_V_FLAG_SUITEB_128_LOS",
- "X509_VERIFY_PARAM_set1_host",
- "X509_VERIFY_PARAM_set1_email",
- "X509_VERIFY_PARAM_set1_ip",
- "X509_VERIFY_PARAM_set1_ip_asc",
- "X509_VERIFY_PARAM_set_hostflags",
- "SSL_get0_param",
- "X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT",
- "X509_CHECK_FLAG_NO_WILDCARDS",
- "X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS",
- "X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS",
- "X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS"
]
def cryptography_has_110_verification_params():
- return [
- "X509_CHECK_FLAG_NEVER_CHECK_SUBJECT"
- ]
-
-
-def cryptography_has_x509_v_flag_trusted_first():
- return [
- "X509_V_FLAG_TRUSTED_FIRST",
- ]
-
-
-def cryptography_has_x509_v_flag_partial_chain():
- return [
- "X509_V_FLAG_PARTIAL_CHAIN",
- ]
+ return ["X509_CHECK_FLAG_NEVER_CHECK_SUBJECT"]
def cryptography_has_set_cert_cb():
@@ -148,35 +74,12 @@ def cryptography_has_tls_st():
]
-def cryptography_has_locking_callbacks():
- return [
- "CRYPTO_LOCK",
- "CRYPTO_UNLOCK",
- "CRYPTO_READ",
- "CRYPTO_LOCK_SSL",
- "CRYPTO_lock",
- "Cryptography_setup_ssl_threads",
- ]
-
-
def cryptography_has_scrypt():
return [
"EVP_PBE_scrypt",
]
-def cryptography_has_generic_dtls_method():
- return [
- "DTLS_method",
- "DTLS_server_method",
- "DTLS_client_method",
- "SSL_OP_NO_DTLSv1",
- "SSL_OP_NO_DTLSv1_2",
- "DTLS_set_link_mtu",
- "DTLS_get_link_min_mtu",
- ]
-
-
def cryptography_has_evp_pkey_dhx():
return [
"EVP_PKEY_DHX",
@@ -197,11 +100,12 @@ def cryptography_has_sct():
"SCT_get0_signature",
"SCT_get_timestamp",
"SCT_set_source",
+ "sk_SCT_new_null",
+ "sk_SCT_free",
"sk_SCT_num",
"sk_SCT_value",
- "SCT_LIST_free",
"sk_SCT_push",
- "sk_SCT_new_null",
+ "SCT_LIST_free",
"SCT_new",
"SCT_set1_log_id",
"SCT_set_timestamp",
@@ -217,20 +121,6 @@ def cryptography_has_x509_store_ctx_get_issuer():
]
-def cryptography_has_x25519():
- return [
- "EVP_PKEY_X25519",
- "NID_X25519",
- ]
-
-
-def cryptography_has_x448():
- return [
- "EVP_PKEY_X448",
- "NID_X448",
- ]
-
-
def cryptography_has_ed448():
return [
"EVP_PKEY_ED448",
@@ -245,6 +135,13 @@ def cryptography_has_ed25519():
]
+def cryptography_has_poly1305():
+ return [
+ "NID_poly1305",
+ "EVP_PKEY_POLY1305",
+ ]
+
+
def cryptography_has_oneshot_evp_digest_sign_verify():
return [
"EVP_DigestSign",
@@ -267,7 +164,7 @@ def cryptography_has_evp_pkey_get_set_tls_encodedpoint():
def cryptography_has_fips():
return [
- "FIPS_set_mode",
+ "FIPS_mode_set",
"FIPS_mode",
]
@@ -301,16 +198,6 @@ def cryptography_has_openssl_cleanup():
]
-def cryptography_has_cipher_details():
- return [
- "SSL_CIPHER_is_aead",
- "SSL_CIPHER_get_cipher_nid",
- "SSL_CIPHER_get_digest_nid",
- "SSL_CIPHER_get_kx_nid",
- "SSL_CIPHER_get_auth_nid",
- ]
-
-
def cryptography_has_tlsv13():
return [
"SSL_OP_NO_TLSv1_3",
@@ -326,6 +213,13 @@ def cryptography_has_tlsv13():
]
+def cryptography_has_keylog():
+ return [
+ "SSL_CTX_set_keylog_callback",
+ "SSL_CTX_get_keylog_callback",
+ ]
+
+
def cryptography_has_raw_key():
return [
"EVP_PKEY_new_raw_private_key",
@@ -335,9 +229,45 @@ def cryptography_has_raw_key():
]
-def cryptography_has_evp_r_memory_limit_exceeded():
+def cryptography_has_engine():
+ return [
+ "ENGINE_by_id",
+ "ENGINE_init",
+ "ENGINE_finish",
+ "ENGINE_get_default_RAND",
+ "ENGINE_set_default_RAND",
+ "ENGINE_unregister_RAND",
+ "ENGINE_ctrl_cmd",
+ "ENGINE_free",
+ "ENGINE_get_name",
+ "Cryptography_add_osrandom_engine",
+ "ENGINE_ctrl_cmd_string",
+ "ENGINE_load_builtin_engines",
+ "ENGINE_load_private_key",
+ "ENGINE_load_public_key",
+ ]
+
+
+def cryptography_has_verified_chain():
+ return [
+ "SSL_get0_verified_chain",
+ ]
+
+
+def cryptography_has_srtp():
return [
- "EVP_R_MEMORY_LIMIT_EXCEEDED",
+ "SSL_CTX_set_tlsext_use_srtp",
+ "SSL_set_tlsext_use_srtp",
+ "SSL_get_selected_srtp_profile",
+ ]
+
+
+def cryptography_has_get_proto_version():
+ return [
+ "SSL_CTX_get_min_proto_version",
+ "SSL_CTX_get_max_proto_version",
+ "SSL_get_min_proto_version",
+ "SSL_get_max_proto_version",
]
@@ -348,50 +278,26 @@ def cryptography_has_evp_r_memory_limit_exceeded():
# lists so we can use coverage to measure which are used.
CONDITIONAL_NAMES = {
"Cryptography_HAS_EC2M": cryptography_has_ec2m,
- "Cryptography_HAS_EC_1_0_2": cryptography_has_ec_1_0_2,
- "Cryptography_HAS_SET_ECDH_AUTO": cryptography_has_set_ecdh_auto,
- "Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR": (
- cryptography_has_rsa_r_pkcs_decoding_error
- ),
"Cryptography_HAS_RSA_OAEP_MD": cryptography_has_rsa_oaep_md,
"Cryptography_HAS_RSA_OAEP_LABEL": cryptography_has_rsa_oaep_label,
"Cryptography_HAS_SSL3_METHOD": cryptography_has_ssl3_method,
- "Cryptography_HAS_ALPN": cryptography_has_alpn,
- "Cryptography_HAS_COMPRESSION": cryptography_has_compression,
- "Cryptography_HAS_GET_SERVER_TMP_KEY": cryptography_has_get_server_tmp_key,
- "Cryptography_HAS_102_VERIFICATION_ERROR_CODES": (
- cryptography_has_102_verification_error_codes
- ),
- "Cryptography_HAS_102_VERIFICATION_PARAMS": (
- cryptography_has_102_verification_params
- ),
+ "Cryptography_HAS_102_VERIFICATION": cryptography_has_102_verification,
"Cryptography_HAS_110_VERIFICATION_PARAMS": (
cryptography_has_110_verification_params
),
- "Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST": (
- cryptography_has_x509_v_flag_trusted_first
- ),
- "Cryptography_HAS_X509_V_FLAG_PARTIAL_CHAIN": (
- cryptography_has_x509_v_flag_partial_chain
- ),
"Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb,
"Cryptography_HAS_SSL_ST": cryptography_has_ssl_st,
"Cryptography_HAS_TLS_ST": cryptography_has_tls_st,
- "Cryptography_HAS_LOCKING_CALLBACKS": cryptography_has_locking_callbacks,
"Cryptography_HAS_SCRYPT": cryptography_has_scrypt,
- "Cryptography_HAS_GENERIC_DTLS_METHOD": (
- cryptography_has_generic_dtls_method
- ),
"Cryptography_HAS_EVP_PKEY_DHX": cryptography_has_evp_pkey_dhx,
"Cryptography_HAS_MEM_FUNCTIONS": cryptography_has_mem_functions,
"Cryptography_HAS_SCT": cryptography_has_sct,
"Cryptography_HAS_X509_STORE_CTX_GET_ISSUER": (
cryptography_has_x509_store_ctx_get_issuer
),
- "Cryptography_HAS_X25519": cryptography_has_x25519,
- "Cryptography_HAS_X448": cryptography_has_x448,
"Cryptography_HAS_ED448": cryptography_has_ed448,
"Cryptography_HAS_ED25519": cryptography_has_ed25519,
+ "Cryptography_HAS_POLY1305": cryptography_has_poly1305,
"Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY": (
cryptography_has_oneshot_evp_digest_sign_verify
),
@@ -403,13 +309,14 @@ CONDITIONAL_NAMES = {
"Cryptography_HAS_PSK": cryptography_has_psk,
"Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext,
"Cryptography_HAS_OPENSSL_CLEANUP": cryptography_has_openssl_cleanup,
- "Cryptography_HAS_CIPHER_DETAILS": cryptography_has_cipher_details,
"Cryptography_HAS_TLSv1_3": cryptography_has_tlsv13,
+ "Cryptography_HAS_KEYLOG": cryptography_has_keylog,
"Cryptography_HAS_RAW_KEY": cryptography_has_raw_key,
"Cryptography_HAS_EVP_DIGESTFINAL_XOF": (
cryptography_has_evp_digestfinal_xof
),
- "Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED": (
- cryptography_has_evp_r_memory_limit_exceeded
- ),
+ "Cryptography_HAS_ENGINE": cryptography_has_engine,
+ "Cryptography_HAS_VERIFIED_CHAIN": cryptography_has_verified_chain,
+ "Cryptography_HAS_SRTP": cryptography_has_srtp,
+ "Cryptography_HAS_GET_PROTO_VERSION": cryptography_has_get_proto_version,
}
diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py
index 0824ea88c..7a84a340e 100644
--- a/src/cryptography/hazmat/bindings/openssl/binding.py
+++ b/src/cryptography/hazmat/bindings/openssl/binding.py
@@ -7,8 +7,8 @@ from __future__ import absolute_import, division, print_function
import collections
import threading
import types
-import warnings
+import cryptography
from cryptography import utils
from cryptography.exceptions import InternalError
from cryptography.hazmat.bindings._openssl import ffi, lib
@@ -51,20 +51,31 @@ def _consume_errors(lib):
return errors
-def _openssl_assert(lib, ok):
- if not ok:
- errors = _consume_errors(lib)
- errors_with_text = []
- for err in errors:
- buf = ffi.new("char[]", 256)
- lib.ERR_error_string_n(err.code, buf, len(buf))
- err_text_reason = ffi.string(buf)
-
- errors_with_text.append(
- _OpenSSLErrorWithText(
- err.code, err.lib, err.func, err.reason, err_text_reason
- )
+def _errors_with_text(errors):
+ errors_with_text = []
+ for err in errors:
+ buf = ffi.new("char[]", 256)
+ lib.ERR_error_string_n(err.code, buf, len(buf))
+ err_text_reason = ffi.string(buf)
+
+ errors_with_text.append(
+ _OpenSSLErrorWithText(
+ err.code, err.lib, err.func, err.reason, err_text_reason
)
+ )
+
+ return errors_with_text
+
+
+def _consume_errors_with_text(lib):
+ return _errors_with_text(_consume_errors(lib))
+
+
+def _openssl_assert(lib, ok, errors=None):
+ if not ok:
+ if errors is None:
+ errors = _consume_errors(lib)
+ errors_with_text = _errors_with_text(errors)
raise InternalError(
"Unknown OpenSSL error. This error is commonly encountered when "
@@ -74,7 +85,7 @@ def _openssl_assert(lib, ok):
"please file an issue at https://github.com/pyca/cryptography/"
"issues with information on how to reproduce "
"this. ({0!r})".format(errors_with_text),
- errors_with_text
+ errors_with_text,
)
@@ -97,11 +108,11 @@ class Binding(object):
"""
OpenSSL API wrapper.
"""
+
lib = None
ffi = ffi
_lib_loaded = False
_init_lock = threading.Lock()
- _lock_init_lock = threading.Lock()
def __init__(self):
self._ensure_ffi_initialized()
@@ -114,10 +125,9 @@ class Binding(object):
# reliably clear the error queue. Once we clear it here we will
# error on any subsequent unexpected item in the stack.
cls.lib.ERR_clear_error()
- cls._osrandom_engine_id = cls.lib.Cryptography_osrandom_engine_id
- cls._osrandom_engine_name = cls.lib.Cryptography_osrandom_engine_name
- result = cls.lib.Cryptography_add_osrandom_engine()
- _openssl_assert(cls.lib, result in (1, 2))
+ if cls.lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE:
+ result = cls.lib.Cryptography_add_osrandom_engine()
+ _openssl_assert(cls.lib, result in (1, 2))
@classmethod
def _ensure_ffi_initialized(cls):
@@ -129,46 +139,34 @@ class Binding(object):
cls.lib.SSL_library_init()
# adds all ciphers/digests for EVP
cls.lib.OpenSSL_add_all_algorithms()
- # loads error strings for libcrypto and libssl functions
- cls.lib.SSL_load_error_strings()
cls._register_osrandom_engine()
@classmethod
def init_static_locks(cls):
- with cls._lock_init_lock:
- cls._ensure_ffi_initialized()
- # Use Python's implementation if available, importing _ssl triggers
- # the setup for this.
- __import__("_ssl")
-
- if (not cls.lib.Cryptography_HAS_LOCKING_CALLBACKS or
- cls.lib.CRYPTO_get_locking_callback() != cls.ffi.NULL):
- return
-
- # If nothing else has setup a locking callback already, we set up
- # our own
- res = lib.Cryptography_setup_ssl_threads()
- _openssl_assert(cls.lib, res == 1)
-
-
-def _verify_openssl_version(lib):
- if (
- lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
- not lib.CRYPTOGRAPHY_IS_LIBRESSL
- ):
- warnings.warn(
- "OpenSSL version 1.0.1 is no longer supported by the OpenSSL "
- "project, please upgrade. A future version of cryptography will "
- "drop support for it.",
- utils.CryptographyDeprecationWarning
+ cls._ensure_ffi_initialized()
+
+
+def _verify_package_version(version):
+ # Occasionally we run into situations where the version of the Python
+ # package does not match the version of the shared object that is loaded.
+ # This may occur in environments where multiple versions of cryptography
+ # are installed and available in the python path. To avoid errors cropping
+ # up later this code checks that the currently imported package and the
+ # shared object that were loaded have the same version and raise an
+ # ImportError if they do not
+ so_package_version = ffi.string(lib.CRYPTOGRAPHY_PACKAGE_VERSION)
+ if version.encode("ascii") != so_package_version:
+ raise ImportError(
+ "The version of cryptography does not match the loaded "
+ "shared object. This can happen if you have multiple copies of "
+ "cryptography installed in your Python path. Please try creating "
+ "a new virtual environment to resolve this issue. "
+ "Loaded python version: {}, shared object version: {}".format(
+ version, so_package_version
+ )
)
-# OpenSSL is not thread safe until the locks are initialized. We call this
-# method in module scope so that it executes with the import lock. On
-# Pythons < 3.4 this import lock is a global lock, which can prevent a race
-# condition registering the OpenSSL locks. On Python 3.4+ the import lock
-# is per module so this approach will not work.
-Binding.init_static_locks()
+_verify_package_version(cryptography.__version__)
-_verify_openssl_version(Binding.lib)
+Binding.init_static_locks()
diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py
index 4fc995245..74a311d50 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/dh.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py
@@ -9,9 +9,14 @@ import abc
import six
from cryptography import utils
+from cryptography.hazmat.backends import _get_backend
-def generate_parameters(generator, key_size, backend):
+_MIN_MODULUS_SIZE = 512
+
+
+def generate_parameters(generator, key_size, backend=None):
+ backend = _get_backend(backend)
return backend.generate_dh_parameters(generator, key_size)
@@ -21,8 +26,9 @@ class DHPrivateNumbers(object):
raise TypeError("x must be an integer.")
if not isinstance(public_numbers, DHPublicNumbers):
- raise TypeError("public_numbers must be an instance of "
- "DHPublicNumbers.")
+ raise TypeError(
+ "public_numbers must be an instance of " "DHPublicNumbers."
+ )
self._x = x
self._public_numbers = public_numbers
@@ -32,14 +38,15 @@ class DHPrivateNumbers(object):
return NotImplemented
return (
- self._x == other._x and
- self._public_numbers == other._public_numbers
+ self._x == other._x
+ and self._public_numbers == other._public_numbers
)
def __ne__(self, other):
return not self == other
- def private_key(self, backend):
+ def private_key(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_dh_private_numbers(self)
public_numbers = utils.read_only_property("_public_numbers")
@@ -53,7 +60,8 @@ class DHPublicNumbers(object):
if not isinstance(parameter_numbers, DHParameterNumbers):
raise TypeError(
- "parameters must be an instance of DHParameterNumbers.")
+ "parameters must be an instance of DHParameterNumbers."
+ )
self._y = y
self._parameter_numbers = parameter_numbers
@@ -63,14 +71,15 @@ class DHPublicNumbers(object):
return NotImplemented
return (
- self._y == other._y and
- self._parameter_numbers == other._parameter_numbers
+ self._y == other._y
+ and self._parameter_numbers == other._parameter_numbers
)
def __ne__(self, other):
return not self == other
- def public_key(self, backend):
+ def public_key(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_dh_public_numbers(self)
y = utils.read_only_property("_y")
@@ -79,9 +88,8 @@ class DHPublicNumbers(object):
class DHParameterNumbers(object):
def __init__(self, p, g, q=None):
- if (
- not isinstance(p, six.integer_types) or
- not isinstance(g, six.integer_types)
+ if not isinstance(p, six.integer_types) or not isinstance(
+ g, six.integer_types
):
raise TypeError("p and g must be integers")
if q is not None and not isinstance(q, six.integer_types):
@@ -90,6 +98,11 @@ class DHParameterNumbers(object):
if g < 2:
raise ValueError("DH generator must be 2 or greater")
+ if p.bit_length() < _MIN_MODULUS_SIZE:
+ raise ValueError(
+ "p (modulus) must be at least {}-bit".format(_MIN_MODULUS_SIZE)
+ )
+
self._p = p
self._g = g
self._q = q
@@ -99,15 +112,14 @@ class DHParameterNumbers(object):
return NotImplemented
return (
- self._p == other._p and
- self._g == other._g and
- self._q == other._q
+ self._p == other._p and self._g == other._g and self._q == other._q
)
def __ne__(self, other):
return not self == other
- def parameters(self, backend):
+ def parameters(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_dh_parameter_numbers(self)
p = utils.read_only_property("_p")
diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
index e380a441f..8ccc66665 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -9,6 +9,7 @@ import abc
import six
from cryptography import utils
+from cryptography.hazmat.backends import _get_backend
@six.add_metaclass(abc.ABCMeta)
@@ -119,17 +120,21 @@ class DSAPublicKey(object):
DSAPublicKeyWithSerialization = DSAPublicKey
-def generate_parameters(key_size, backend):
+def generate_parameters(key_size, backend=None):
+ backend = _get_backend(backend)
return backend.generate_dsa_parameters(key_size)
-def generate_private_key(key_size, backend):
+def generate_private_key(key_size, backend=None):
+ backend = _get_backend(backend)
return backend.generate_dsa_private_key_and_parameters(key_size)
def _check_dsa_parameters(parameters):
- if parameters.p.bit_length() not in [1024, 2048, 3072]:
- raise ValueError("p must be exactly 1024, 2048, or 3072 bits long")
+ if parameters.p.bit_length() not in [1024, 2048, 3072, 4096]:
+ raise ValueError(
+ "p must be exactly 1024, 2048, 3072, or 4096 bits long"
+ )
if parameters.q.bit_length() not in [160, 224, 256]:
raise ValueError("q must be exactly 160, 224, or 256 bits long")
@@ -150,9 +155,9 @@ def _check_dsa_private_numbers(numbers):
class DSAParameterNumbers(object):
def __init__(self, p, q, g):
if (
- not isinstance(p, six.integer_types) or
- not isinstance(q, six.integer_types) or
- not isinstance(g, six.integer_types)
+ not isinstance(p, six.integer_types)
+ or not isinstance(q, six.integer_types)
+ or not isinstance(g, six.integer_types)
):
raise TypeError(
"DSAParameterNumbers p, q, and g arguments must be integers."
@@ -166,7 +171,8 @@ class DSAParameterNumbers(object):
q = utils.read_only_property("_q")
g = utils.read_only_property("_g")
- def parameters(self, backend):
+ def parameters(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_dsa_parameter_numbers(self)
def __eq__(self, other):
@@ -180,9 +186,8 @@ class DSAParameterNumbers(object):
def __repr__(self):
return (
- "<DSAParameterNumbers(p={self.p}, q={self.q}, g={self.g})>".format(
- self=self
- )
+ "<DSAParameterNumbers(p={self.p}, q={self.q}, "
+ "g={self.g})>".format(self=self)
)
@@ -202,7 +207,8 @@ class DSAPublicNumbers(object):
y = utils.read_only_property("_y")
parameter_numbers = utils.read_only_property("_parameter_numbers")
- def public_key(self, backend):
+ def public_key(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_dsa_public_numbers(self)
def __eq__(self, other):
@@ -210,8 +216,8 @@ class DSAPublicNumbers(object):
return NotImplemented
return (
- self.y == other.y and
- self.parameter_numbers == other.parameter_numbers
+ self.y == other.y
+ and self.parameter_numbers == other.parameter_numbers
)
def __ne__(self, other):
@@ -239,7 +245,8 @@ class DSAPrivateNumbers(object):
x = utils.read_only_property("_x")
public_numbers = utils.read_only_property("_public_numbers")
- def private_key(self, backend):
+ def private_key(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_dsa_private_numbers(self)
def __eq__(self, other):
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py
index 1de0976a6..c7e694fc5 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/ec.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py
@@ -11,6 +11,7 @@ import six
from cryptography import utils
from cryptography.hazmat._oid import ObjectIdentifier
+from cryptography.hazmat.backends import _get_backend
class EllipticCurveOID(object):
@@ -166,6 +167,7 @@ class EllipticCurvePublicKey(object):
raise ValueError("Unsupported elliptic curve point type")
from cryptography.hazmat.backends.openssl.backend import backend
+
return backend.load_elliptic_curve_public_bytes(curve, data)
@@ -289,26 +291,22 @@ class BrainpoolP512R1(object):
_CURVE_TYPES = {
"prime192v1": SECP192R1,
"prime256v1": SECP256R1,
-
"secp192r1": SECP192R1,
"secp224r1": SECP224R1,
"secp256r1": SECP256R1,
"secp384r1": SECP384R1,
"secp521r1": SECP521R1,
"secp256k1": SECP256K1,
-
"sect163k1": SECT163K1,
"sect233k1": SECT233K1,
"sect283k1": SECT283K1,
"sect409k1": SECT409K1,
"sect571k1": SECT571K1,
-
"sect163r2": SECT163R2,
"sect233r1": SECT233R1,
"sect283r1": SECT283R1,
"sect409r1": SECT409R1,
"sect571r1": SECT571R1,
-
"brainpoolP256r1": BrainpoolP256R1,
"brainpoolP384r1": BrainpoolP384R1,
"brainpoolP512r1": BrainpoolP512R1,
@@ -323,11 +321,13 @@ class ECDSA(object):
algorithm = utils.read_only_property("_algorithm")
-def generate_private_key(curve, backend):
+def generate_private_key(curve, backend=None):
+ backend = _get_backend(backend)
return backend.generate_elliptic_curve_private_key(curve)
-def derive_private_key(private_value, curve, backend):
+def derive_private_key(private_value, curve, backend=None):
+ backend = _get_backend(backend)
if not isinstance(private_value, six.integer_types):
raise TypeError("private_value must be an integer type.")
@@ -342,9 +342,8 @@ def derive_private_key(private_value, curve, backend):
class EllipticCurvePublicNumbers(object):
def __init__(self, x, y, curve):
- if (
- not isinstance(x, six.integer_types) or
- not isinstance(y, six.integer_types)
+ if not isinstance(x, six.integer_types) or not isinstance(
+ y, six.integer_types
):
raise TypeError("x and y must be integers.")
@@ -355,7 +354,8 @@ class EllipticCurvePublicNumbers(object):
self._x = x
self._curve = curve
- def public_key(self, backend):
+ def public_key(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_elliptic_curve_public_numbers(self)
def encode_point(self):
@@ -364,14 +364,15 @@ class EllipticCurvePublicNumbers(object):
" and will be removed in a future version. Please use "
"EllipticCurvePublicKey.public_bytes to obtain both "
"compressed and uncompressed point encoding.",
- utils.DeprecatedIn25,
+ utils.PersistentlyDeprecated2019,
stacklevel=2,
)
# key_size is in bits. Convert to bytes and round up
byte_length = (self.curve.key_size + 7) // 8
return (
- b'\x04' + utils.int_to_bytes(self.x, byte_length) +
- utils.int_to_bytes(self.y, byte_length)
+ b"\x04"
+ + utils.int_to_bytes(self.x, byte_length)
+ + utils.int_to_bytes(self.y, byte_length)
)
@classmethod
@@ -383,21 +384,21 @@ class EllipticCurvePublicNumbers(object):
"Support for unsafe construction of public numbers from "
"encoded data will be removed in a future version. "
"Please use EllipticCurvePublicKey.from_encoded_point",
- utils.DeprecatedIn25,
+ utils.PersistentlyDeprecated2019,
stacklevel=2,
)
- if data.startswith(b'\x04'):
+ if data.startswith(b"\x04"):
# key_size is in bits. Convert to bytes and round up
byte_length = (curve.key_size + 7) // 8
if len(data) == 2 * byte_length + 1:
- x = utils.int_from_bytes(data[1:byte_length + 1], 'big')
- y = utils.int_from_bytes(data[byte_length + 1:], 'big')
+ x = utils.int_from_bytes(data[1 : byte_length + 1], "big")
+ y = utils.int_from_bytes(data[byte_length + 1 :], "big")
return cls(x, y, curve)
else:
- raise ValueError('Invalid elliptic curve point data length')
+ raise ValueError("Invalid elliptic curve point data length")
else:
- raise ValueError('Unsupported elliptic curve point type')
+ raise ValueError("Unsupported elliptic curve point type")
curve = utils.read_only_property("_curve")
x = utils.read_only_property("_x")
@@ -408,10 +409,10 @@ class EllipticCurvePublicNumbers(object):
return NotImplemented
return (
- self.x == other.x and
- self.y == other.y and
- self.curve.name == other.curve.name and
- self.curve.key_size == other.curve.key_size
+ self.x == other.x
+ and self.y == other.y
+ and self.curve.name == other.curve.name
+ and self.curve.key_size == other.curve.key_size
)
def __ne__(self, other):
@@ -441,7 +442,8 @@ class EllipticCurvePrivateNumbers(object):
self._private_value = private_value
self._public_numbers = public_numbers
- def private_key(self, backend):
+ def private_key(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_elliptic_curve_private_numbers(self)
private_value = utils.read_only_property("_private_value")
@@ -452,8 +454,8 @@ class EllipticCurvePrivateNumbers(object):
return NotImplemented
return (
- self.private_value == other.private_value and
- self.public_numbers == other.public_numbers
+ self.private_value == other.private_value
+ and self.public_numbers == other.public_numbers
)
def __ne__(self, other):
@@ -465,3 +467,36 @@ class EllipticCurvePrivateNumbers(object):
class ECDH(object):
pass
+
+
+_OID_TO_CURVE = {
+ EllipticCurveOID.SECP192R1: SECP192R1,
+ EllipticCurveOID.SECP224R1: SECP224R1,
+ EllipticCurveOID.SECP256K1: SECP256K1,
+ EllipticCurveOID.SECP256R1: SECP256R1,
+ EllipticCurveOID.SECP384R1: SECP384R1,
+ EllipticCurveOID.SECP521R1: SECP521R1,
+ EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1,
+ EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1,
+ EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1,
+ EllipticCurveOID.SECT163K1: SECT163K1,
+ EllipticCurveOID.SECT163R2: SECT163R2,
+ EllipticCurveOID.SECT233K1: SECT233K1,
+ EllipticCurveOID.SECT233R1: SECT233R1,
+ EllipticCurveOID.SECT283K1: SECT283K1,
+ EllipticCurveOID.SECT283R1: SECT283R1,
+ EllipticCurveOID.SECT409K1: SECT409K1,
+ EllipticCurveOID.SECT409R1: SECT409R1,
+ EllipticCurveOID.SECT571K1: SECT571K1,
+ EllipticCurveOID.SECT571R1: SECT571R1,
+}
+
+
+def get_curve_for_oid(oid):
+ try:
+ return _OID_TO_CURVE[oid]
+ except KeyError:
+ raise LookupError(
+ "The provided object identifier has no matching elliptic "
+ "curve class"
+ )
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py
new file mode 100644
index 000000000..2d07a029b
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py
@@ -0,0 +1,87 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import abc
+
+import six
+
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+
+
+_ED25519_KEY_SIZE = 32
+_ED25519_SIG_SIZE = 64
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Ed25519PublicKey(object):
+ @classmethod
+ def from_public_bytes(cls, data):
+ from cryptography.hazmat.backends.openssl.backend import backend
+
+ if not backend.ed25519_supported():
+ raise UnsupportedAlgorithm(
+ "ed25519 is not supported by this version of OpenSSL.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+ )
+
+ return backend.ed25519_load_public_bytes(data)
+
+ @abc.abstractmethod
+ def public_bytes(self, encoding, format):
+ """
+ The serialized bytes of the public key.
+ """
+
+ @abc.abstractmethod
+ def verify(self, signature, data):
+ """
+ Verify the signature.
+ """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Ed25519PrivateKey(object):
+ @classmethod
+ def generate(cls):
+ from cryptography.hazmat.backends.openssl.backend import backend
+
+ if not backend.ed25519_supported():
+ raise UnsupportedAlgorithm(
+ "ed25519 is not supported by this version of OpenSSL.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+ )
+
+ return backend.ed25519_generate_key()
+
+ @classmethod
+ def from_private_bytes(cls, data):
+ from cryptography.hazmat.backends.openssl.backend import backend
+
+ if not backend.ed25519_supported():
+ raise UnsupportedAlgorithm(
+ "ed25519 is not supported by this version of OpenSSL.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+ )
+
+ return backend.ed25519_load_private_bytes(data)
+
+ @abc.abstractmethod
+ def public_key(self):
+ """
+ The Ed25519PublicKey derived from the private key.
+ """
+
+ @abc.abstractmethod
+ def private_bytes(self, encoding, format, encryption_algorithm):
+ """
+ The serialized bytes of the private key.
+ """
+
+ @abc.abstractmethod
+ def sign(self, data):
+ """
+ Signs the data.
+ """
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed448.py b/src/cryptography/hazmat/primitives/asymmetric/ed448.py
new file mode 100644
index 000000000..520ffcbcb
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/asymmetric/ed448.py
@@ -0,0 +1,82 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import abc
+
+import six
+
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Ed448PublicKey(object):
+ @classmethod
+ def from_public_bytes(cls, data):
+ from cryptography.hazmat.backends.openssl.backend import backend
+
+ if not backend.ed448_supported():
+ raise UnsupportedAlgorithm(
+ "ed448 is not supported by this version of OpenSSL.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+ )
+
+ return backend.ed448_load_public_bytes(data)
+
+ @abc.abstractmethod
+ def public_bytes(self, encoding, format):
+ """
+ The serialized bytes of the public key.
+ """
+
+ @abc.abstractmethod
+ def verify(self, signature, data):
+ """
+ Verify the signature.
+ """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Ed448PrivateKey(object):
+ @classmethod
+ def generate(cls):
+ from cryptography.hazmat.backends.openssl.backend import backend
+
+ if not backend.ed448_supported():
+ raise UnsupportedAlgorithm(
+ "ed448 is not supported by this version of OpenSSL.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+ )
+ return backend.ed448_generate_key()
+
+ @classmethod
+ def from_private_bytes(cls, data):
+ from cryptography.hazmat.backends.openssl.backend import backend
+
+ if not backend.ed448_supported():
+ raise UnsupportedAlgorithm(
+ "ed448 is not supported by this version of OpenSSL.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
+ )
+
+ return backend.ed448_load_private_bytes(data)
+
+ @abc.abstractmethod
+ def public_key(self):
+ """
+ The Ed448PublicKey derived from the private key.
+ """
+
+ @abc.abstractmethod
+ def sign(self, data):
+ """
+ Signs the data.
+ """
+
+ @abc.abstractmethod
+ def private_bytes(self, encoding, format, encryption_algorithm):
+ """
+ The serialized bytes of the private key.
+ """
diff --git a/src/cryptography/hazmat/primitives/asymmetric/padding.py b/src/cryptography/hazmat/primitives/asymmetric/padding.py
index a37c3f90c..fc8f6e26a 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/padding.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/padding.py
@@ -5,7 +5,6 @@
from __future__ import absolute_import, division, print_function
import abc
-import math
import six
@@ -36,8 +35,10 @@ class PSS(object):
def __init__(self, mgf, salt_length):
self._mgf = mgf
- if (not isinstance(salt_length, six.integer_types) and
- salt_length is not self.MAX_LENGTH):
+ if (
+ not isinstance(salt_length, six.integer_types)
+ and salt_length is not self.MAX_LENGTH
+ ):
raise TypeError("salt_length must be an integer.")
if salt_length is not self.MAX_LENGTH and salt_length < 0:
@@ -73,7 +74,7 @@ def calculate_max_pss_salt_length(key, hash_algorithm):
if not isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)):
raise TypeError("key must be an RSA public or private key")
# bit length - 1 per RFC 3447
- emlen = int(math.ceil((key.key_size - 1) / 8.0))
+ emlen = (key.key_size + 6) // 8
salt_length = emlen - hash_algorithm.digest_size - 2
assert salt_length >= 0
return salt_length
diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
index 27db671af..ea16bbf66 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -5,6 +5,7 @@
from __future__ import absolute_import, division, print_function
import abc
+
try:
# Only available in math in 3.5+
from math import gcd
@@ -15,6 +16,7 @@ import six
from cryptography import utils
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import RSABackend
@@ -104,15 +106,22 @@ class RSAPublicKey(object):
Verifies the signature of the data.
"""
+ @abc.abstractmethod
+ def recover_data_from_signature(self, signature, padding, algorithm):
+ """
+ Recovers the original data from the signature.
+ """
+
RSAPublicKeyWithSerialization = RSAPublicKey
-def generate_private_key(public_exponent, key_size, backend):
+def generate_private_key(public_exponent, key_size, backend=None):
+ backend = _get_backend(backend)
if not isinstance(backend, RSABackend):
raise UnsupportedAlgorithm(
"Backend object does not implement RSABackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
_verify_rsa_parameters(public_exponent, key_size)
@@ -120,18 +129,19 @@ def generate_private_key(public_exponent, key_size, backend):
def _verify_rsa_parameters(public_exponent, key_size):
- if public_exponent < 3:
- raise ValueError("public_exponent must be >= 3.")
-
- if public_exponent & 1 == 0:
- raise ValueError("public_exponent must be odd.")
+ if public_exponent not in (3, 65537):
+ raise ValueError(
+ "public_exponent must be either 3 (for legacy compatibility) or "
+ "65537. Almost everyone should choose 65537 here!"
+ )
if key_size < 512:
raise ValueError("key_size must be at least 512-bits.")
-def _check_private_key_components(p, q, private_exponent, dmp1, dmq1, iqmp,
- public_exponent, modulus):
+def _check_private_key_components(
+ p, q, private_exponent, dmp1, dmq1, iqmp, public_exponent, modulus
+):
if modulus < 3:
raise ValueError("modulus must be >= 3.")
@@ -184,12 +194,12 @@ def _modinv(e, m):
"""
Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1
"""
- x1, y1, x2, y2 = 1, 0, 0, 1
+ x1, x2 = 1, 0
a, b = e, m
while b > 0:
q, r = divmod(a, b)
- xn, yn = x1 - q * x2, y1 - q * y2
- a, b, x1, y1, x2, y2 = b, r, x2, y2, xn, yn
+ xn = x1 - q * x2
+ a, b, x1, x2 = b, r, x2, xn
return x1 % m
@@ -266,15 +276,14 @@ def rsa_recover_prime_factors(n, e, d):
class RSAPrivateNumbers(object):
- def __init__(self, p, q, d, dmp1, dmq1, iqmp,
- public_numbers):
+ def __init__(self, p, q, d, dmp1, dmq1, iqmp, public_numbers):
if (
- not isinstance(p, six.integer_types) or
- not isinstance(q, six.integer_types) or
- not isinstance(d, six.integer_types) or
- not isinstance(dmp1, six.integer_types) or
- not isinstance(dmq1, six.integer_types) or
- not isinstance(iqmp, six.integer_types)
+ not isinstance(p, six.integer_types)
+ or not isinstance(q, six.integer_types)
+ or not isinstance(d, six.integer_types)
+ or not isinstance(dmp1, six.integer_types)
+ or not isinstance(dmq1, six.integer_types)
+ or not isinstance(iqmp, six.integer_types)
):
raise TypeError(
"RSAPrivateNumbers p, q, d, dmp1, dmq1, iqmp arguments must"
@@ -303,7 +312,8 @@ class RSAPrivateNumbers(object):
iqmp = utils.read_only_property("_iqmp")
public_numbers = utils.read_only_property("_public_numbers")
- def private_key(self, backend):
+ def private_key(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_rsa_private_numbers(self)
def __eq__(self, other):
@@ -311,35 +321,36 @@ class RSAPrivateNumbers(object):
return NotImplemented
return (
- self.p == other.p and
- self.q == other.q and
- self.d == other.d and
- self.dmp1 == other.dmp1 and
- self.dmq1 == other.dmq1 and
- self.iqmp == other.iqmp and
- self.public_numbers == other.public_numbers
+ self.p == other.p
+ and self.q == other.q
+ and self.d == other.d
+ and self.dmp1 == other.dmp1
+ and self.dmq1 == other.dmq1
+ and self.iqmp == other.iqmp
+ and self.public_numbers == other.public_numbers
)
def __ne__(self, other):
return not self == other
def __hash__(self):
- return hash((
- self.p,
- self.q,
- self.d,
- self.dmp1,
- self.dmq1,
- self.iqmp,
- self.public_numbers,
- ))
+ return hash(
+ (
+ self.p,
+ self.q,
+ self.d,
+ self.dmp1,
+ self.dmq1,
+ self.iqmp,
+ self.public_numbers,
+ )
+ )
class RSAPublicNumbers(object):
def __init__(self, e, n):
- if (
- not isinstance(e, six.integer_types) or
- not isinstance(n, six.integer_types)
+ if not isinstance(e, six.integer_types) or not isinstance(
+ n, six.integer_types
):
raise TypeError("RSAPublicNumbers arguments must be integers.")
@@ -349,7 +360,8 @@ class RSAPublicNumbers(object):
e = utils.read_only_property("_e")
n = utils.read_only_property("_n")
- def public_key(self, backend):
+ def public_key(self, backend=None):
+ backend = _get_backend(backend)
return backend.load_rsa_public_numbers(self)
def __repr__(self):
diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py
index ef1e7eb92..5f9b67786 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/utils.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py
@@ -4,49 +4,30 @@
from __future__ import absolute_import, division, print_function
-import warnings
-
-from asn1crypto.algos import DSASignature
-
-import six
-
from cryptography import utils
+from cryptography.hazmat._der import (
+ DERReader,
+ INTEGER,
+ SEQUENCE,
+ encode_der,
+ encode_der_integer,
+)
from cryptography.hazmat.primitives import hashes
-def decode_rfc6979_signature(signature):
- warnings.warn(
- "decode_rfc6979_signature is deprecated and will "
- "be removed in a future version, use decode_dss_signature instead.",
- utils.PersistentlyDeprecated,
- stacklevel=2
- )
- return decode_dss_signature(signature)
-
-
def decode_dss_signature(signature):
- data = DSASignature.load(signature, strict=True).native
- return data['r'], data['s']
-
-
-def encode_rfc6979_signature(r, s):
- warnings.warn(
- "encode_rfc6979_signature is deprecated and will "
- "be removed in a future version, use encode_dss_signature instead.",
- utils.PersistentlyDeprecated,
- stacklevel=2
- )
- return encode_dss_signature(r, s)
+ with DERReader(signature).read_single_element(SEQUENCE) as seq:
+ r = seq.read_element(INTEGER).as_integer()
+ s = seq.read_element(INTEGER).as_integer()
+ return r, s
def encode_dss_signature(r, s):
- if (
- not isinstance(r, six.integer_types) or
- not isinstance(s, six.integer_types)
- ):
- raise ValueError("Both r and s must be integers")
-
- return DSASignature({'r': r, 's': s}).dump()
+ return encode_der(
+ SEQUENCE,
+ encode_der(INTEGER, encode_der_integer(r)),
+ encode_der(INTEGER, encode_der_integer(s)),
+ )
class Prehashed(object):
diff --git a/src/cryptography/hazmat/primitives/asymmetric/x25519.py b/src/cryptography/hazmat/primitives/asymmetric/x25519.py
index 4e8badf43..fc6369153 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/x25519.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/x25519.py
@@ -16,16 +16,17 @@ class X25519PublicKey(object):
@classmethod
def from_public_bytes(cls, data):
from cryptography.hazmat.backends.openssl.backend import backend
+
if not backend.x25519_supported():
raise UnsupportedAlgorithm(
"X25519 is not supported by this version of OpenSSL.",
- _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+ _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
)
return backend.x25519_load_public_bytes(data)
@abc.abstractmethod
- def public_bytes(self, encoding=None, format=None):
+ def public_bytes(self, encoding, format):
"""
The serialized bytes of the public key.
"""
@@ -36,20 +37,22 @@ class X25519PrivateKey(object):
@classmethod
def generate(cls):
from cryptography.hazmat.backends.openssl.backend import backend
+
if not backend.x25519_supported():
raise UnsupportedAlgorithm(
"X25519 is not supported by this version of OpenSSL.",
- _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+ _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
)
return backend.x25519_generate_key()
@classmethod
def from_private_bytes(cls, data):
from cryptography.hazmat.backends.openssl.backend import backend
+
if not backend.x25519_supported():
raise UnsupportedAlgorithm(
"X25519 is not supported by this version of OpenSSL.",
- _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+ _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
)
return backend.x25519_load_private_bytes(data)
diff --git a/src/cryptography/hazmat/primitives/asymmetric/x448.py b/src/cryptography/hazmat/primitives/asymmetric/x448.py
index 475e678ff..3ac067bfd 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/x448.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/x448.py
@@ -16,10 +16,11 @@ class X448PublicKey(object):
@classmethod
def from_public_bytes(cls, data):
from cryptography.hazmat.backends.openssl.backend import backend
+
if not backend.x448_supported():
raise UnsupportedAlgorithm(
"X448 is not supported by this version of OpenSSL.",
- _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+ _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
)
return backend.x448_load_public_bytes(data)
@@ -36,20 +37,22 @@ class X448PrivateKey(object):
@classmethod
def generate(cls):
from cryptography.hazmat.backends.openssl.backend import backend
+
if not backend.x448_supported():
raise UnsupportedAlgorithm(
"X448 is not supported by this version of OpenSSL.",
- _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+ _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
)
return backend.x448_generate_key()
@classmethod
def from_private_bytes(cls, data):
from cryptography.hazmat.backends.openssl.backend import backend
+
if not backend.x448_supported():
raise UnsupportedAlgorithm(
"X448 is not supported by this version of OpenSSL.",
- _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+ _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
)
return backend.x448_load_private_bytes(data)
diff --git a/src/cryptography/hazmat/primitives/ciphers/__init__.py b/src/cryptography/hazmat/primitives/ciphers/__init__.py
index 171b1c693..4380f72b2 100644
--- a/src/cryptography/hazmat/primitives/ciphers/__init__.py
+++ b/src/cryptography/hazmat/primitives/ciphers/__init__.py
@@ -5,8 +5,13 @@
from __future__ import absolute_import, division, print_function
from cryptography.hazmat.primitives.ciphers.base import (
- AEADCipherContext, AEADDecryptionContext, AEADEncryptionContext,
- BlockCipherAlgorithm, Cipher, CipherAlgorithm, CipherContext
+ AEADCipherContext,
+ AEADDecryptionContext,
+ AEADEncryptionContext,
+ BlockCipherAlgorithm,
+ Cipher,
+ CipherAlgorithm,
+ CipherContext,
)
diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py
index 42e19adb1..c8c93955c 100644
--- a/src/cryptography/hazmat/primitives/ciphers/aead.py
+++ b/src/cryptography/hazmat/primitives/ciphers/aead.py
@@ -18,7 +18,7 @@ class ChaCha20Poly1305(object):
if not backend.aead_cipher_supported(self):
raise exceptions.UnsupportedAlgorithm(
"ChaCha20Poly1305 is not supported by this version of OpenSSL",
- exceptions._Reasons.UNSUPPORTED_CIPHER
+ exceptions._Reasons.UNSUPPORTED_CIPHER,
)
utils._check_byteslike("key", key)
@@ -42,18 +42,14 @@ class ChaCha20Poly1305(object):
)
self._check_params(nonce, data, associated_data)
- return aead._encrypt(
- backend, self, nonce, data, associated_data, 16
- )
+ return aead._encrypt(backend, self, nonce, data, associated_data, 16)
def decrypt(self, nonce, data, associated_data):
if associated_data is None:
associated_data = b""
self._check_params(nonce, data, associated_data)
- return aead._decrypt(
- backend, self, nonce, data, associated_data, 16
- )
+ return aead._decrypt(backend, self, nonce, data, associated_data, 16)
def _check_params(self, nonce, data, associated_data):
utils._check_byteslike("nonce", nonce)
@@ -80,12 +76,6 @@ class AESCCM(object):
self._tag_length = tag_length
- if not backend.aead_cipher_supported(self):
- raise exceptions.UnsupportedAlgorithm(
- "AESCCM is not supported by this version of OpenSSL",
- exceptions._Reasons.UNSUPPORTED_CIPHER
- )
-
@classmethod
def generate_key(cls, bit_length):
if not isinstance(bit_length, int):
@@ -126,7 +116,7 @@ class AESCCM(object):
# https://tools.ietf.org/html/rfc3610#section-2.1
l_val = 15 - len(nonce)
if 2 ** (8 * l_val) < data_len:
- raise ValueError("Nonce too long for data")
+ raise ValueError("Data too long for nonce")
def _check_params(self, nonce, data, associated_data):
utils._check_byteslike("nonce", nonce)
@@ -167,22 +157,18 @@ class AESGCM(object):
)
self._check_params(nonce, data, associated_data)
- return aead._encrypt(
- backend, self, nonce, data, associated_data, 16
- )
+ return aead._encrypt(backend, self, nonce, data, associated_data, 16)
def decrypt(self, nonce, data, associated_data):
if associated_data is None:
associated_data = b""
self._check_params(nonce, data, associated_data)
- return aead._decrypt(
- backend, self, nonce, data, associated_data, 16
- )
+ return aead._decrypt(backend, self, nonce, data, associated_data, 16)
def _check_params(self, nonce, data, associated_data):
utils._check_byteslike("nonce", nonce)
utils._check_bytes("data", data)
utils._check_bytes("associated_data", associated_data)
- if len(nonce) == 0:
- raise ValueError("Nonce must be at least 1 byte")
+ if len(nonce) < 8 or len(nonce) > 128:
+ raise ValueError("Nonce must be between 8 and 128 bytes")
diff --git a/src/cryptography/hazmat/primitives/ciphers/algorithms.py b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
index 1f49fd9de..8072cedd1 100644
--- a/src/cryptography/hazmat/primitives/ciphers/algorithms.py
+++ b/src/cryptography/hazmat/primitives/ciphers/algorithms.py
@@ -6,7 +6,8 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.hazmat.primitives.ciphers import (
- BlockCipherAlgorithm, CipherAlgorithm
+ BlockCipherAlgorithm,
+ CipherAlgorithm,
)
from cryptography.hazmat.primitives.ciphers.modes import ModeWithNonce
@@ -17,9 +18,11 @@ def _verify_key_size(algorithm, key):
# Verify that the key size matches the expected key size
if len(key) * 8 not in algorithm.key_sizes:
- raise ValueError("Invalid key size ({0}) for {1}.".format(
- len(key) * 8, algorithm.name
- ))
+ raise ValueError(
+ "Invalid key size ({}) for {}.".format(
+ len(key) * 8, algorithm.name
+ )
+ )
return key
diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py
index f85704142..dae425a29 100644
--- a/src/cryptography/hazmat/primitives/ciphers/base.py
+++ b/src/cryptography/hazmat/primitives/ciphers/base.py
@@ -10,9 +10,13 @@ import six
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, AlreadyUpdated, NotYetFinalized, UnsupportedAlgorithm,
- _Reasons
+ AlreadyFinalized,
+ AlreadyUpdated,
+ NotYetFinalized,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import CipherBackend
from cryptography.hazmat.primitives.ciphers import modes
@@ -94,11 +98,12 @@ class AEADEncryptionContext(object):
class Cipher(object):
- def __init__(self, algorithm, mode, backend):
+ def __init__(self, algorithm, mode, backend=None):
+ backend = _get_backend(backend)
if not isinstance(backend, CipherBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement CipherBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
if not isinstance(algorithm, CipherAlgorithm):
@@ -179,7 +184,7 @@ class _AEADCipherContext(object):
self._bytes_processed += data_size
if self._bytes_processed > self._ctx._mode._MAX_ENCRYPTED_BYTES:
raise ValueError(
- "{0} has a maximum encrypted byte limit of {1}".format(
+ "{} has a maximum encrypted byte limit of {}".format(
self._ctx._mode.name, self._ctx._mode._MAX_ENCRYPTED_BYTES
)
)
@@ -217,7 +222,7 @@ class _AEADCipherContext(object):
self._aad_bytes_processed += len(data)
if self._aad_bytes_processed > self._ctx._mode._MAX_AAD_BYTES:
raise ValueError(
- "{0} has a maximum AAD byte limit of {1}".format(
+ "{} has a maximum AAD byte limit of {}".format(
self._ctx._mode.name, self._ctx._mode._MAX_AAD_BYTES
)
)
@@ -230,6 +235,7 @@ class _AEADEncryptionContext(_AEADCipherContext):
@property
def tag(self):
if self._ctx is not None:
- raise NotYetFinalized("You must finalize encryption before "
- "getting the tag.")
+ raise NotYetFinalized(
+ "You must finalize encryption before " "getting the tag."
+ )
return self._tag
diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py
index ad91a6e14..0ba0f2b5a 100644
--- a/src/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/src/cryptography/hazmat/primitives/ciphers/modes.py
@@ -72,9 +72,11 @@ def _check_aes_key_length(self, algorithm):
def _check_iv_length(self, algorithm):
if len(self.initialization_vector) * 8 != algorithm.block_size:
- raise ValueError("Invalid IV size ({0}) for {1}.".format(
- len(self.initialization_vector), self.name
- ))
+ raise ValueError(
+ "Invalid IV size ({}) for {}.".format(
+ len(self.initialization_vector), self.name
+ )
+ )
def _check_iv_and_key_length(self, algorithm):
@@ -178,9 +180,11 @@ class CTR(object):
def validate_for_algorithm(self, algorithm):
_check_aes_key_length(self, algorithm)
if len(self.nonce) * 8 != algorithm.block_size:
- raise ValueError("Invalid nonce size ({0}) for {1}.".format(
- len(self.nonce), self.name
- ))
+ raise ValueError(
+ "Invalid nonce size ({}) for {}.".format(
+ len(self.nonce), self.name
+ )
+ )
@utils.register_interface(Mode)
@@ -192,12 +196,14 @@ class GCM(object):
_MAX_AAD_BYTES = (2 ** 64) // 8
def __init__(self, initialization_vector, tag=None, min_tag_length=16):
- # len(initialization_vector) must in [1, 2 ** 64), but it's impossible
- # to actually construct a bytes object that large, so we don't check
- # for it
+ # OpenSSL 3.0.0 constrains GCM IVs to [64, 1024] bits inclusive
+ # This is a sane limit anyway so we'll enforce it here.
utils._check_byteslike("initialization_vector", initialization_vector)
- if len(initialization_vector) == 0:
- raise ValueError("initialization_vector must be at least 1 byte")
+ if len(initialization_vector) < 8 or len(initialization_vector) > 128:
+ raise ValueError(
+ "initialization_vector must be between 8 and 128 bytes (64 "
+ "and 1024 bits)."
+ )
self._initialization_vector = initialization_vector
if tag is not None:
utils._check_bytes("tag", tag)
@@ -205,8 +211,9 @@ class GCM(object):
raise ValueError("min_tag_length must be >= 4")
if len(tag) < min_tag_length:
raise ValueError(
- "Authentication tag must be {0} bytes or longer.".format(
- min_tag_length)
+ "Authentication tag must be {} bytes or longer.".format(
+ min_tag_length
+ )
)
self._tag = tag
self._min_tag_length = min_tag_length
diff --git a/src/cryptography/hazmat/primitives/cmac.py b/src/cryptography/hazmat/primitives/cmac.py
index 1404eac3d..bf962c906 100644
--- a/src/cryptography/hazmat/primitives/cmac.py
+++ b/src/cryptography/hazmat/primitives/cmac.py
@@ -6,25 +6,26 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import CMACBackend
-from cryptography.hazmat.primitives import ciphers, mac
+from cryptography.hazmat.primitives import ciphers
-@utils.register_interface(mac.MACContext)
class CMAC(object):
- def __init__(self, algorithm, backend, ctx=None):
+ def __init__(self, algorithm, backend=None, ctx=None):
+ backend = _get_backend(backend)
if not isinstance(backend, CMACBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement CMACBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
if not isinstance(algorithm, ciphers.BlockCipherAlgorithm):
- raise TypeError(
- "Expected instance of BlockCipherAlgorithm."
- )
+ raise TypeError("Expected instance of BlockCipherAlgorithm.")
self._algorithm = algorithm
self._backend = backend
@@ -59,7 +60,5 @@ class CMAC(object):
if self._ctx is None:
raise AlreadyFinalized("Context was already finalized.")
return CMAC(
- self._algorithm,
- backend=self._backend,
- ctx=self._ctx.copy()
+ self._algorithm, backend=self._backend, ctx=self._ctx.copy()
)
diff --git a/src/cryptography/hazmat/primitives/constant_time.py b/src/cryptography/hazmat/primitives/constant_time.py
index 0e987ea75..7f41b9efa 100644
--- a/src/cryptography/hazmat/primitives/constant_time.py
+++ b/src/cryptography/hazmat/primitives/constant_time.py
@@ -5,31 +5,10 @@
from __future__ import absolute_import, division, print_function
import hmac
-import warnings
-from cryptography import utils
-from cryptography.hazmat.bindings._constant_time import lib
+def bytes_eq(a, b):
+ if not isinstance(a, bytes) or not isinstance(b, bytes):
+ raise TypeError("a and b must be bytes.")
-if hasattr(hmac, "compare_digest"):
- def bytes_eq(a, b):
- if not isinstance(a, bytes) or not isinstance(b, bytes):
- raise TypeError("a and b must be bytes.")
-
- return hmac.compare_digest(a, b)
-
-else:
- warnings.warn(
- "Support for your Python version is deprecated. The next version of "
- "cryptography will remove support. Please upgrade to a 2.7.x "
- "release that supports hmac.compare_digest as soon as possible.",
- utils.DeprecatedIn23,
- )
-
- def bytes_eq(a, b):
- if not isinstance(a, bytes) or not isinstance(b, bytes):
- raise TypeError("a and b must be bytes.")
-
- return lib.Cryptography_constant_time_bytes_eq(
- a, len(a), b, len(b)
- ) == 1
+ return hmac.compare_digest(a, b)
diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py
index 9be2b6009..18e2bab36 100644
--- a/src/cryptography/hazmat/primitives/hashes.py
+++ b/src/cryptography/hazmat/primitives/hashes.py
@@ -10,8 +10,11 @@ import six
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import HashBackend
@@ -66,11 +69,12 @@ class ExtendableOutputFunction(object):
@utils.register_interface(HashContext)
class Hash(object):
- def __init__(self, algorithm, backend, ctx=None):
+ def __init__(self, algorithm, backend=None, ctx=None):
+ backend = _get_backend(backend)
if not isinstance(backend, HashBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HashBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
if not isinstance(algorithm, HashAlgorithm):
diff --git a/src/cryptography/hazmat/primitives/hmac.py b/src/cryptography/hazmat/primitives/hmac.py
index f7f401d2b..8c421dc68 100644
--- a/src/cryptography/hazmat/primitives/hmac.py
+++ b/src/cryptography/hazmat/primitives/hmac.py
@@ -6,20 +6,23 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import HMACBackend
-from cryptography.hazmat.primitives import hashes, mac
+from cryptography.hazmat.primitives import hashes
-@utils.register_interface(mac.MACContext)
@utils.register_interface(hashes.HashContext)
class HMAC(object):
- def __init__(self, key, algorithm, backend, ctx=None):
+ def __init__(self, key, algorithm, backend=None, ctx=None):
+ backend = _get_backend(backend)
if not isinstance(backend, HMACBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HMACBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
if not isinstance(algorithm, hashes.HashAlgorithm):
@@ -48,7 +51,7 @@ class HMAC(object):
self._key,
self.algorithm,
backend=self._backend,
- ctx=self._ctx.copy()
+ ctx=self._ctx.copy(),
)
def finalize(self):
diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py
index 65b25cdc2..7cc0324fc 100644
--- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py
@@ -8,8 +8,12 @@ import struct
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized,
+ InvalidKey,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.backends.interfaces import HashBackend
from cryptography.hazmat.primitives import constant_time, hashes, hmac
@@ -17,16 +21,15 @@ from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
def _int_to_u32be(n):
- return struct.pack('>I', n)
+ return struct.pack(">I", n)
def _common_args_checks(algorithm, length, otherinfo):
max_length = algorithm.digest_size * (2 ** 32 - 1)
if length > max_length:
raise ValueError(
- "Can not derive keys larger than {0} bits.".format(
- max_length
- ))
+ "Can not derive keys larger than {} bits.".format(max_length)
+ )
if otherinfo is not None:
utils._check_bytes("otherinfo", otherinfo)
@@ -37,7 +40,7 @@ def _concatkdf_derive(key_material, length, auxfn, otherinfo):
outlen = 0
counter = 1
- while (length > outlen):
+ while length > outlen:
h = auxfn()
h.update(_int_to_u32be(counter))
h.update(key_material)
@@ -51,7 +54,8 @@ def _concatkdf_derive(key_material, length, auxfn, otherinfo):
@utils.register_interface(KeyDerivationFunction)
class ConcatKDFHash(object):
- def __init__(self, algorithm, length, otherinfo, backend):
+ def __init__(self, algorithm, length, otherinfo, backend=None):
+ backend = _get_backend(backend)
_common_args_checks(algorithm, length, otherinfo)
self._algorithm = algorithm
@@ -63,7 +67,7 @@ class ConcatKDFHash(object):
if not isinstance(backend, HashBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HashBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
self._backend = backend
self._used = False
@@ -75,8 +79,9 @@ class ConcatKDFHash(object):
if self._used:
raise AlreadyFinalized
self._used = True
- return _concatkdf_derive(key_material, self._length,
- self._hash, self._otherinfo)
+ return _concatkdf_derive(
+ key_material, self._length, self._hash, self._otherinfo
+ )
def verify(self, key_material, expected_key):
if not constant_time.bytes_eq(self.derive(key_material), expected_key):
@@ -85,7 +90,8 @@ class ConcatKDFHash(object):
@utils.register_interface(KeyDerivationFunction)
class ConcatKDFHMAC(object):
- def __init__(self, algorithm, length, salt, otherinfo, backend):
+ def __init__(self, algorithm, length, salt, otherinfo, backend=None):
+ backend = _get_backend(backend)
_common_args_checks(algorithm, length, otherinfo)
self._algorithm = algorithm
@@ -104,7 +110,7 @@ class ConcatKDFHMAC(object):
if not isinstance(backend, HMACBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HMACBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
self._backend = backend
self._used = False
@@ -116,8 +122,9 @@ class ConcatKDFHMAC(object):
if self._used:
raise AlreadyFinalized
self._used = True
- return _concatkdf_derive(key_material, self._length,
- self._hmac, self._otherinfo)
+ return _concatkdf_derive(
+ key_material, self._length, self._hmac, self._otherinfo
+ )
def verify(self, key_material, expected_key):
if not constant_time.bytes_eq(self.derive(key_material), expected_key):
diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py
index 307f91cca..9bb6bc213 100644
--- a/src/cryptography/hazmat/primitives/kdf/hkdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py
@@ -8,8 +8,12 @@ import six
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized,
+ InvalidKey,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time, hmac
from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
@@ -17,11 +21,12 @@ from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
@utils.register_interface(KeyDerivationFunction)
class HKDF(object):
- def __init__(self, algorithm, length, salt, info, backend):
+ def __init__(self, algorithm, length, salt, info, backend=None):
+ backend = _get_backend(backend)
if not isinstance(backend, HMACBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HMACBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
self._algorithm = algorithm
@@ -53,11 +58,12 @@ class HKDF(object):
@utils.register_interface(KeyDerivationFunction)
class HKDFExpand(object):
- def __init__(self, algorithm, length, info, backend):
+ def __init__(self, algorithm, length, info, backend=None):
+ backend = _get_backend(backend)
if not isinstance(backend, HMACBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HMACBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
self._algorithm = algorithm
@@ -68,9 +74,8 @@ class HKDFExpand(object):
if length > max_length:
raise ValueError(
- "Can not derive keys larger than {0} octets.".format(
- max_length
- ))
+ "Can not derive keys larger than {} octets.".format(max_length)
+ )
self._length = length
@@ -95,7 +100,7 @@ class HKDFExpand(object):
output.append(h.finalize())
counter += 1
- return b"".join(output)[:self._length]
+ return b"".join(output)[: self._length]
def derive(self, key_material):
utils._check_byteslike("key_material", key_material)
diff --git a/src/cryptography/hazmat/primitives/kdf/kbkdf.py b/src/cryptography/hazmat/primitives/kdf/kbkdf.py
index 56783a85c..864337001 100644
--- a/src/cryptography/hazmat/primitives/kdf/kbkdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/kbkdf.py
@@ -10,8 +10,12 @@ from six.moves import range
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized,
+ InvalidKey,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time, hashes, hmac
from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
@@ -28,24 +32,36 @@ class CounterLocation(Enum):
@utils.register_interface(KeyDerivationFunction)
class KBKDFHMAC(object):
- def __init__(self, algorithm, mode, length, rlen, llen,
- location, label, context, fixed, backend):
+ def __init__(
+ self,
+ algorithm,
+ mode,
+ length,
+ rlen,
+ llen,
+ location,
+ label,
+ context,
+ fixed,
+ backend=None,
+ ):
+ backend = _get_backend(backend)
if not isinstance(backend, HMACBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HMACBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
if not isinstance(algorithm, hashes.HashAlgorithm):
raise UnsupportedAlgorithm(
"Algorithm supplied is not a supported hash algorithm.",
- _Reasons.UNSUPPORTED_HASH
+ _Reasons.UNSUPPORTED_HASH,
)
if not backend.hmac_supported(algorithm):
raise UnsupportedAlgorithm(
"Algorithm supplied is not a supported hmac algorithm.",
- _Reasons.UNSUPPORTED_HASH
+ _Reasons.UNSUPPORTED_HASH,
)
if not isinstance(mode, Mode):
@@ -55,8 +71,9 @@ class KBKDFHMAC(object):
raise TypeError("location must be of type CounterLocation")
if (label or context) and fixed:
- raise ValueError("When supplying fixed data, "
- "label and context are ignored.")
+ raise ValueError(
+ "When supplying fixed data, " "label and context are ignored."
+ )
if rlen is None or not self._valid_byte_length(rlen):
raise ValueError("rlen must be between 1 and 4")
@@ -68,10 +85,10 @@ class KBKDFHMAC(object):
raise TypeError("llen must be an integer")
if label is None:
- label = b''
+ label = b""
if context is None:
- context = b''
+ context = b""
utils._check_bytes("label", label)
utils._check_bytes("context", context)
@@ -89,7 +106,7 @@ class KBKDFHMAC(object):
def _valid_byte_length(self, value):
if not isinstance(value, int):
- raise TypeError('value must be of type int')
+ raise TypeError("value must be of type int")
value_bin = utils.int_to_bytes(1, value)
if not 1 <= len(value_bin) <= 4:
@@ -106,7 +123,7 @@ class KBKDFHMAC(object):
# inverse floor division (equivalent to ceiling)
rounds = -(-self._length // self._algorithm.digest_size)
- output = [b'']
+ output = [b""]
# For counter mode, the number of iterations shall not be
# larger than 2^r-1, where r <= 32 is the binary length of the counter
@@ -114,7 +131,7 @@ class KBKDFHMAC(object):
# PRF will not repeat during a particular call to the KDF function.
r_bin = utils.int_to_bytes(1, self._rlen)
if rounds > pow(2, len(r_bin) * 8) - 1:
- raise ValueError('There are too many iterations.')
+ raise ValueError("There are too many iterations.")
for i in range(1, rounds + 1):
h = hmac.HMAC(key_material, self._algorithm, backend=self._backend)
@@ -130,7 +147,7 @@ class KBKDFHMAC(object):
output.append(h.finalize())
- return b''.join(output)[:self._length]
+ return b"".join(output)[: self._length]
def _generate_fixed_input(self):
if self._fixed_data and isinstance(self._fixed_data, bytes):
diff --git a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py
index a47b7bbcb..5b67d48bb 100644
--- a/src/cryptography/hazmat/primitives/kdf/pbkdf2.py
+++ b/src/cryptography/hazmat/primitives/kdf/pbkdf2.py
@@ -6,8 +6,12 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized,
+ InvalidKey,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import PBKDF2HMACBackend
from cryptography.hazmat.primitives import constant_time
from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
@@ -15,18 +19,20 @@ from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
@utils.register_interface(KeyDerivationFunction)
class PBKDF2HMAC(object):
- def __init__(self, algorithm, length, salt, iterations, backend):
+ def __init__(self, algorithm, length, salt, iterations, backend=None):
+ backend = _get_backend(backend)
if not isinstance(backend, PBKDF2HMACBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement PBKDF2HMACBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
if not backend.pbkdf2_hmac_supported(algorithm):
raise UnsupportedAlgorithm(
- "{0} is not supported for PBKDF2 by this backend.".format(
- algorithm.name),
- _Reasons.UNSUPPORTED_HASH
+ "{} is not supported for PBKDF2 by this backend.".format(
+ algorithm.name
+ ),
+ _Reasons.UNSUPPORTED_HASH,
)
self._used = False
self._algorithm = algorithm
@@ -47,7 +53,7 @@ class PBKDF2HMAC(object):
self._length,
self._salt,
self._iterations,
- key_material
+ key_material,
)
def verify(self, key_material, expected_key):
diff --git a/src/cryptography/hazmat/primitives/kdf/scrypt.py b/src/cryptography/hazmat/primitives/kdf/scrypt.py
index df9745e68..f028646aa 100644
--- a/src/cryptography/hazmat/primitives/kdf/scrypt.py
+++ b/src/cryptography/hazmat/primitives/kdf/scrypt.py
@@ -8,8 +8,12 @@ import sys
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized,
+ InvalidKey,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import ScryptBackend
from cryptography.hazmat.primitives import constant_time
from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
@@ -22,11 +26,12 @@ _MEM_LIMIT = sys.maxsize // 2
@utils.register_interface(KeyDerivationFunction)
class Scrypt(object):
- def __init__(self, salt, length, n, r, p, backend):
+ def __init__(self, salt, length, n, r, p, backend=None):
+ backend = _get_backend(backend)
if not isinstance(backend, ScryptBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement ScryptBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
self._length = length
diff --git a/src/cryptography/hazmat/primitives/kdf/x963kdf.py b/src/cryptography/hazmat/primitives/kdf/x963kdf.py
index fd9d125e7..1898d526a 100644
--- a/src/cryptography/hazmat/primitives/kdf/x963kdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/x963kdf.py
@@ -8,25 +8,31 @@ import struct
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized,
+ InvalidKey,
+ UnsupportedAlgorithm,
+ _Reasons,
)
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import HashBackend
from cryptography.hazmat.primitives import constant_time, hashes
from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
def _int_to_u32be(n):
- return struct.pack('>I', n)
+ return struct.pack(">I", n)
@utils.register_interface(KeyDerivationFunction)
class X963KDF(object):
- def __init__(self, algorithm, length, sharedinfo, backend):
+ def __init__(self, algorithm, length, sharedinfo, backend=None):
+ backend = _get_backend(backend)
max_len = algorithm.digest_size * (2 ** 32 - 1)
if length > max_len:
raise ValueError(
- "Can not derive keys larger than {0} bits.".format(max_len))
+ "Can not derive keys larger than {} bits.".format(max_len)
+ )
if sharedinfo is not None:
utils._check_bytes("sharedinfo", sharedinfo)
@@ -37,7 +43,7 @@ class X963KDF(object):
if not isinstance(backend, HashBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HashBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
self._backend = backend
self._used = False
@@ -61,7 +67,7 @@ class X963KDF(object):
outlen += len(output[-1])
counter += 1
- return b"".join(output)[:self._length]
+ return b"".join(output)[: self._length]
def verify(self, key_material, expected_key):
if not constant_time.bytes_eq(self.derive(key_material), expected_key):
diff --git a/src/cryptography/hazmat/primitives/keywrap.py b/src/cryptography/hazmat/primitives/keywrap.py
index f55c519cf..2439cafe6 100644
--- a/src/cryptography/hazmat/primitives/keywrap.py
+++ b/src/cryptography/hazmat/primitives/keywrap.py
@@ -6,6 +6,7 @@ from __future__ import absolute_import, division, print_function
import struct
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.modes import ECB
@@ -33,7 +34,8 @@ def _wrap_core(wrapping_key, a, r, backend):
return a + b"".join(r)
-def aes_key_wrap(wrapping_key, key_to_wrap, backend):
+def aes_key_wrap(wrapping_key, key_to_wrap, backend=None):
+ backend = _get_backend(backend)
if len(wrapping_key) not in [16, 24, 32]:
raise ValueError("The wrapping key must be a valid AES key length")
@@ -44,7 +46,7 @@ def aes_key_wrap(wrapping_key, key_to_wrap, backend):
raise ValueError("The key to wrap must be a multiple of 8 bytes")
a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6"
- r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]
+ r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)]
return _wrap_core(wrapping_key, a, r, backend)
@@ -55,9 +57,12 @@ def _unwrap_core(wrapping_key, a, r, backend):
for j in reversed(range(6)):
for i in reversed(range(n)):
# pack/unpack are safe as these are always 64-bit chunks
- atr = struct.pack(
- ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1)
- ) + r[i]
+ atr = (
+ struct.pack(
+ ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1)
+ )
+ + r[i]
+ )
# every decryption operation is a discrete 16 byte chunk so
# it is safe to reuse the decryptor for the entire operation
b = decryptor.update(atr)
@@ -68,7 +73,8 @@ def _unwrap_core(wrapping_key, a, r, backend):
return a, r
-def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend):
+def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend=None):
+ backend = _get_backend(backend)
if len(wrapping_key) not in [16, 24, 32]:
raise ValueError("The wrapping key must be a valid AES key length")
@@ -83,11 +89,12 @@ def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend):
assert encryptor.finalize() == b""
return b
else:
- r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]
+ r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)]
return _wrap_core(wrapping_key, aiv, r, backend)
-def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend):
+def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend=None):
+ backend = _get_backend(backend)
if len(wrapped_key) < 16:
raise InvalidUnwrap("Must be at least 16 bytes")
@@ -103,7 +110,7 @@ def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend):
data = b[8:]
n = 1
else:
- r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]
+ r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)]
encrypted_aiv = r.pop(0)
n = len(r)
a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend)
@@ -117,10 +124,9 @@ def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend):
(mli,) = struct.unpack(">I", a[4:])
b = (8 * n) - mli
if (
- not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") or not
- 8 * (n - 1) < mli <= 8 * n or (
- b != 0 and not bytes_eq(data[-b:], b"\x00" * b)
- )
+ not bytes_eq(a[:4], b"\xa6\x59\x59\xa6")
+ or not 8 * (n - 1) < mli <= 8 * n
+ or (b != 0 and not bytes_eq(data[-b:], b"\x00" * b))
):
raise InvalidUnwrap()
@@ -130,7 +136,8 @@ def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend):
return data[:-b]
-def aes_key_unwrap(wrapping_key, wrapped_key, backend):
+def aes_key_unwrap(wrapping_key, wrapped_key, backend=None):
+ backend = _get_backend(backend)
if len(wrapped_key) < 24:
raise InvalidUnwrap("Must be at least 24 bytes")
@@ -141,7 +148,7 @@ def aes_key_unwrap(wrapping_key, wrapped_key, backend):
raise ValueError("The wrapping key must be a valid AES key length")
aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6"
- r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]
+ r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)]
a = r.pop(0)
a, r = _unwrap_core(wrapping_key, a, r, backend)
if not bytes_eq(a, aiv):
diff --git a/src/cryptography/hazmat/primitives/mac.py b/src/cryptography/hazmat/primitives/mac.py
deleted file mode 100644
index 4c95190ba..000000000
--- a/src/cryptography/hazmat/primitives/mac.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-from __future__ import absolute_import, division, print_function
-
-import abc
-
-import six
-
-
-@six.add_metaclass(abc.ABCMeta)
-class MACContext(object):
- @abc.abstractmethod
- def update(self, data):
- """
- Processes the provided bytes.
- """
-
- @abc.abstractmethod
- def finalize(self):
- """
- Returns the message authentication code as bytes.
- """
-
- @abc.abstractmethod
- def copy(self):
- """
- Return a MACContext that is a copy of the current context.
- """
-
- @abc.abstractmethod
- def verify(self, signature):
- """
- Checks if the generated message authentication code matches the
- signature.
- """
diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py
index 170c80218..98abffbc0 100644
--- a/src/cryptography/hazmat/primitives/padding.py
+++ b/src/cryptography/hazmat/primitives/padding.py
@@ -40,14 +40,17 @@ def _byte_padding_update(buffer_, data, block_size):
if buffer_ is None:
raise AlreadyFinalized("Context was already finalized.")
- utils._check_bytes("data", data)
+ utils._check_byteslike("data", data)
- buffer_ += data
+ # six.PY2: Only coerce non-bytes objects to avoid triggering bad behavior
+ # of future's newbytes type. Unconditionally call bytes() after Python 2
+ # support is gone.
+ buffer_ += data if isinstance(data, bytes) else bytes(data)
finished_blocks = len(buffer_) // (block_size // 8)
- result = buffer_[:finished_blocks * (block_size // 8)]
- buffer_ = buffer_[finished_blocks * (block_size // 8):]
+ result = buffer_[: finished_blocks * (block_size // 8)]
+ buffer_ = buffer_[finished_blocks * (block_size // 8) :]
return buffer_, result
@@ -64,14 +67,17 @@ def _byte_unpadding_update(buffer_, data, block_size):
if buffer_ is None:
raise AlreadyFinalized("Context was already finalized.")
- utils._check_bytes("data", data)
+ utils._check_byteslike("data", data)
- buffer_ += data
+ # six.PY2: Only coerce non-bytes objects to avoid triggering bad behavior
+ # of future's newbytes type. Unconditionally call bytes() after Python 2
+ # support is gone.
+ buffer_ += data if isinstance(data, bytes) else bytes(data)
finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0)
- result = buffer_[:finished_blocks * (block_size // 8)]
- buffer_ = buffer_[finished_blocks * (block_size // 8):]
+ result = buffer_[: finished_blocks * (block_size // 8)]
+ buffer_ = buffer_[finished_blocks * (block_size // 8) :]
return buffer_, result
@@ -113,7 +119,8 @@ class _PKCS7PaddingContext(object):
def update(self, data):
self._buffer, result = _byte_padding_update(
- self._buffer, data, self.block_size)
+ self._buffer, data, self.block_size
+ )
return result
def _padding(self, size):
@@ -121,7 +128,8 @@ class _PKCS7PaddingContext(object):
def finalize(self):
result = _byte_padding_pad(
- self._buffer, self.block_size, self._padding)
+ self._buffer, self.block_size, self._padding
+ )
self._buffer = None
return result
@@ -135,13 +143,14 @@ class _PKCS7UnpaddingContext(object):
def update(self, data):
self._buffer, result = _byte_unpadding_update(
- self._buffer, data, self.block_size)
+ self._buffer, data, self.block_size
+ )
return result
def finalize(self):
result = _byte_unpadding_check(
- self._buffer, self.block_size,
- lib.Cryptography_check_pkcs7_padding)
+ self._buffer, self.block_size, lib.Cryptography_check_pkcs7_padding
+ )
self._buffer = None
return result
@@ -167,7 +176,8 @@ class _ANSIX923PaddingContext(object):
def update(self, data):
self._buffer, result = _byte_padding_update(
- self._buffer, data, self.block_size)
+ self._buffer, data, self.block_size
+ )
return result
def _padding(self, size):
@@ -175,7 +185,8 @@ class _ANSIX923PaddingContext(object):
def finalize(self):
result = _byte_padding_pad(
- self._buffer, self.block_size, self._padding)
+ self._buffer, self.block_size, self._padding
+ )
self._buffer = None
return result
@@ -189,12 +200,15 @@ class _ANSIX923UnpaddingContext(object):
def update(self, data):
self._buffer, result = _byte_unpadding_update(
- self._buffer, data, self.block_size)
+ self._buffer, data, self.block_size
+ )
return result
def finalize(self):
result = _byte_unpadding_check(
- self._buffer, self.block_size,
- lib.Cryptography_check_ansix923_padding)
+ self._buffer,
+ self.block_size,
+ lib.Cryptography_check_ansix923_padding,
+ )
self._buffer = None
return result
diff --git a/src/cryptography/hazmat/primitives/poly1305.py b/src/cryptography/hazmat/primitives/poly1305.py
new file mode 100644
index 000000000..643968620
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/poly1305.py
@@ -0,0 +1,58 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+
+from cryptography import utils
+from cryptography.exceptions import (
+ AlreadyFinalized,
+ UnsupportedAlgorithm,
+ _Reasons,
+)
+
+
+class Poly1305(object):
+ def __init__(self, key):
+ from cryptography.hazmat.backends.openssl.backend import backend
+
+ if not backend.poly1305_supported():
+ raise UnsupportedAlgorithm(
+ "poly1305 is not supported by this version of OpenSSL.",
+ _Reasons.UNSUPPORTED_MAC,
+ )
+ self._ctx = backend.create_poly1305_ctx(key)
+
+ def update(self, data):
+ if self._ctx is None:
+ raise AlreadyFinalized("Context was already finalized.")
+ utils._check_byteslike("data", data)
+ self._ctx.update(data)
+
+ def finalize(self):
+ if self._ctx is None:
+ raise AlreadyFinalized("Context was already finalized.")
+ mac = self._ctx.finalize()
+ self._ctx = None
+ return mac
+
+ def verify(self, tag):
+ utils._check_bytes("tag", tag)
+ if self._ctx is None:
+ raise AlreadyFinalized("Context was already finalized.")
+
+ ctx, self._ctx = self._ctx, None
+ ctx.verify(tag)
+
+ @classmethod
+ def generate_tag(cls, key, data):
+ p = Poly1305(key)
+ p.update(data)
+ return p.finalize()
+
+ @classmethod
+ def verify_tag(cls, key, data, tag):
+ p = Poly1305(key)
+ p.update(data)
+ p.verify(tag)
diff --git a/src/cryptography/hazmat/primitives/serialization/__init__.py b/src/cryptography/hazmat/primitives/serialization/__init__.py
index f6d4ce994..c2f9b014a 100644
--- a/src/cryptography/hazmat/primitives/serialization/__init__.py
+++ b/src/cryptography/hazmat/primitives/serialization/__init__.py
@@ -5,22 +5,40 @@
from __future__ import absolute_import, division, print_function
from cryptography.hazmat.primitives.serialization.base import (
- BestAvailableEncryption, Encoding, KeySerializationEncryption,
- NoEncryption, ParameterFormat, PrivateFormat, PublicFormat,
- load_der_parameters, load_der_private_key, load_der_public_key,
- load_pem_parameters, load_pem_private_key, load_pem_public_key,
+ BestAvailableEncryption,
+ Encoding,
+ KeySerializationEncryption,
+ NoEncryption,
+ ParameterFormat,
+ PrivateFormat,
+ PublicFormat,
+ load_der_parameters,
+ load_der_private_key,
+ load_der_public_key,
+ load_pem_parameters,
+ load_pem_private_key,
+ load_pem_public_key,
)
from cryptography.hazmat.primitives.serialization.ssh import (
- load_ssh_public_key
+ load_ssh_private_key,
+ load_ssh_public_key,
)
-_PEM_DER = (Encoding.PEM, Encoding.DER)
-
__all__ = [
- "load_der_parameters", "load_der_private_key", "load_der_public_key",
- "load_pem_parameters", "load_pem_private_key", "load_pem_public_key",
- "load_ssh_public_key", "Encoding", "PrivateFormat", "PublicFormat",
- "ParameterFormat", "KeySerializationEncryption", "BestAvailableEncryption",
+ "load_der_parameters",
+ "load_der_private_key",
+ "load_der_public_key",
+ "load_pem_parameters",
+ "load_pem_private_key",
+ "load_pem_public_key",
+ "load_ssh_private_key",
+ "load_ssh_public_key",
+ "Encoding",
+ "PrivateFormat",
+ "PublicFormat",
+ "ParameterFormat",
+ "KeySerializationEncryption",
+ "BestAvailableEncryption",
"NoEncryption",
]
diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py
index 4218ea824..fc27235c5 100644
--- a/src/cryptography/hazmat/primitives/serialization/base.py
+++ b/src/cryptography/hazmat/primitives/serialization/base.py
@@ -10,29 +10,36 @@ from enum import Enum
import six
from cryptography import utils
+from cryptography.hazmat.backends import _get_backend
-def load_pem_private_key(data, password, backend):
+def load_pem_private_key(data, password, backend=None):
+ backend = _get_backend(backend)
return backend.load_pem_private_key(data, password)
-def load_pem_public_key(data, backend):
+def load_pem_public_key(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_pem_public_key(data)
-def load_pem_parameters(data, backend):
+def load_pem_parameters(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_pem_parameters(data)
-def load_der_private_key(data, password, backend):
+def load_der_private_key(data, password, backend=None):
+ backend = _get_backend(backend)
return backend.load_der_private_key(data, password)
-def load_der_public_key(data, backend):
+def load_der_public_key(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_der_public_key(data)
-def load_der_parameters(data, backend):
+def load_der_parameters(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_der_parameters(data)
@@ -42,12 +49,14 @@ class Encoding(Enum):
OpenSSH = "OpenSSH"
Raw = "Raw"
X962 = "ANSI X9.62"
+ SMIME = "S/MIME"
class PrivateFormat(Enum):
PKCS8 = "PKCS8"
TraditionalOpenSSL = "TraditionalOpenSSL"
Raw = "Raw"
+ OpenSSH = "OpenSSH"
class PublicFormat(Enum):
diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py
index 98161d57a..201f32941 100644
--- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py
+++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py
@@ -4,6 +4,47 @@
from __future__ import absolute_import, division, print_function
+from cryptography import x509
+from cryptography.hazmat.backends import _get_backend
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
-def load_key_and_certificates(data, password, backend):
+
+def load_key_and_certificates(data, password, backend=None):
+ backend = _get_backend(backend)
return backend.load_key_and_certificates_from_pkcs12(data, password)
+
+
+def serialize_key_and_certificates(name, key, cert, cas, encryption_algorithm):
+ if key is not None and not isinstance(
+ key,
+ (
+ rsa.RSAPrivateKeyWithSerialization,
+ dsa.DSAPrivateKeyWithSerialization,
+ ec.EllipticCurvePrivateKeyWithSerialization,
+ ),
+ ):
+ raise TypeError("Key must be RSA, DSA, or EllipticCurve private key.")
+ if cert is not None and not isinstance(cert, x509.Certificate):
+ raise TypeError("cert must be a certificate")
+
+ if cas is not None:
+ cas = list(cas)
+ if not all(isinstance(val, x509.Certificate) for val in cas):
+ raise TypeError("all values in cas must be certificates")
+
+ if not isinstance(
+ encryption_algorithm, serialization.KeySerializationEncryption
+ ):
+ raise TypeError(
+ "Key encryption algorithm must be a "
+ "KeySerializationEncryption instance"
+ )
+
+ if key is None and cert is None and not cas:
+ raise ValueError("You must supply at least one of key, cert, or cas")
+
+ backend = _get_backend(None)
+ return backend.serialize_key_and_certificates_to_pkcs12(
+ name, key, cert, cas, encryption_algorithm
+ )
diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py
new file mode 100644
index 000000000..1e11e28ef
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py
@@ -0,0 +1,132 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+from enum import Enum
+
+from cryptography import x509
+from cryptography.hazmat.backends import _get_backend
+from cryptography.hazmat.primitives import hashes, serialization
+from cryptography.hazmat.primitives.asymmetric import ec, rsa
+from cryptography.utils import _check_byteslike
+
+
+def load_pem_pkcs7_certificates(data):
+ backend = _get_backend(None)
+ return backend.load_pem_pkcs7_certificates(data)
+
+
+def load_der_pkcs7_certificates(data):
+ backend = _get_backend(None)
+ return backend.load_der_pkcs7_certificates(data)
+
+
+class PKCS7SignatureBuilder(object):
+ def __init__(self, data=None, signers=[], additional_certs=[]):
+ self._data = data
+ self._signers = signers
+ self._additional_certs = additional_certs
+
+ def set_data(self, data):
+ _check_byteslike("data", data)
+ if self._data is not None:
+ raise ValueError("data may only be set once")
+
+ return PKCS7SignatureBuilder(data, self._signers)
+
+ def add_signer(self, certificate, private_key, hash_algorithm):
+ if not isinstance(
+ hash_algorithm,
+ (
+ hashes.SHA1,
+ hashes.SHA224,
+ hashes.SHA256,
+ hashes.SHA384,
+ hashes.SHA512,
+ ),
+ ):
+ raise TypeError(
+ "hash_algorithm must be one of hashes.SHA1, SHA224, "
+ "SHA256, SHA384, or SHA512"
+ )
+ if not isinstance(certificate, x509.Certificate):
+ raise TypeError("certificate must be a x509.Certificate")
+
+ if not isinstance(
+ private_key, (rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey)
+ ):
+ raise TypeError("Only RSA & EC keys are supported at this time.")
+
+ return PKCS7SignatureBuilder(
+ self._data,
+ self._signers + [(certificate, private_key, hash_algorithm)],
+ )
+
+ def add_certificate(self, certificate):
+ if not isinstance(certificate, x509.Certificate):
+ raise TypeError("certificate must be a x509.Certificate")
+
+ return PKCS7SignatureBuilder(
+ self._data, self._signers, self._additional_certs + [certificate]
+ )
+
+ def sign(self, encoding, options, backend=None):
+ if len(self._signers) == 0:
+ raise ValueError("Must have at least one signer")
+ if self._data is None:
+ raise ValueError("You must add data to sign")
+ options = list(options)
+ if not all(isinstance(x, PKCS7Options) for x in options):
+ raise ValueError("options must be from the PKCS7Options enum")
+ if encoding not in (
+ serialization.Encoding.PEM,
+ serialization.Encoding.DER,
+ serialization.Encoding.SMIME,
+ ):
+ raise ValueError(
+ "Must be PEM, DER, or SMIME from the Encoding enum"
+ )
+
+ # Text is a meaningless option unless it is accompanied by
+ # DetachedSignature
+ if (
+ PKCS7Options.Text in options
+ and PKCS7Options.DetachedSignature not in options
+ ):
+ raise ValueError(
+ "When passing the Text option you must also pass "
+ "DetachedSignature"
+ )
+
+ if PKCS7Options.Text in options and encoding in (
+ serialization.Encoding.DER,
+ serialization.Encoding.PEM,
+ ):
+ raise ValueError(
+ "The Text option is only available for SMIME serialization"
+ )
+
+ # No attributes implies no capabilities so we'll error if you try to
+ # pass both.
+ if (
+ PKCS7Options.NoAttributes in options
+ and PKCS7Options.NoCapabilities in options
+ ):
+ raise ValueError(
+ "NoAttributes is a superset of NoCapabilities. Do not pass "
+ "both values."
+ )
+
+ backend = _get_backend(backend)
+ return backend.pkcs7_sign(self, encoding, options)
+
+
+class PKCS7Options(Enum):
+ Text = "Add text/plain MIME type"
+ Binary = "Don't translate input data into canonical MIME format"
+ DetachedSignature = "Don't embed data in the PKCS7 structure"
+ NoCapabilities = "Don't embed SMIME capabilities"
+ NoAttributes = "Don't embed authenticatedAttributes"
+ NoCerts = "Don't embed signer certificate"
diff --git a/src/cryptography/hazmat/primitives/serialization/ssh.py b/src/cryptography/hazmat/primitives/serialization/ssh.py
index cb838927d..5ecae59f8 100644
--- a/src/cryptography/hazmat/primitives/serialization/ssh.py
+++ b/src/cryptography/hazmat/primitives/serialization/ssh.py
@@ -4,139 +4,680 @@
from __future__ import absolute_import, division, print_function
-import base64
+import binascii
+import os
+import re
import struct
import six
from cryptography import utils
from cryptography.exceptions import UnsupportedAlgorithm
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
-
-
-def load_ssh_public_key(data, backend):
- key_parts = data.split(b' ', 2)
-
- if len(key_parts) < 2:
- raise ValueError(
- 'Key is not in the proper format or contains extra data.')
-
- key_type = key_parts[0]
-
- if key_type == b'ssh-rsa':
- loader = _load_ssh_rsa_public_key
- elif key_type == b'ssh-dss':
- loader = _load_ssh_dss_public_key
- elif key_type in [
- b'ecdsa-sha2-nistp256', b'ecdsa-sha2-nistp384', b'ecdsa-sha2-nistp521',
- ]:
- loader = _load_ssh_ecdsa_public_key
- else:
- raise UnsupportedAlgorithm('Key type is not supported.')
-
- key_body = key_parts[1]
-
- try:
- decoded_data = base64.b64decode(key_body)
- except TypeError:
- raise ValueError('Key is not in the proper format.')
-
- inner_key_type, rest = _ssh_read_next_string(decoded_data)
-
- if inner_key_type != key_type:
+from cryptography.hazmat.backends import _get_backend
+from cryptography.hazmat.primitives.asymmetric import dsa, ec, ed25519, rsa
+from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
+from cryptography.hazmat.primitives.serialization import (
+ Encoding,
+ NoEncryption,
+ PrivateFormat,
+ PublicFormat,
+)
+
+try:
+ from bcrypt import kdf as _bcrypt_kdf
+
+ _bcrypt_supported = True
+except ImportError:
+ _bcrypt_supported = False
+
+ def _bcrypt_kdf(*args, **kwargs):
+ raise UnsupportedAlgorithm("Need bcrypt module")
+
+
+try:
+ from base64 import encodebytes as _base64_encode
+except ImportError:
+ from base64 import encodestring as _base64_encode
+
+_SSH_ED25519 = b"ssh-ed25519"
+_SSH_RSA = b"ssh-rsa"
+_SSH_DSA = b"ssh-dss"
+_ECDSA_NISTP256 = b"ecdsa-sha2-nistp256"
+_ECDSA_NISTP384 = b"ecdsa-sha2-nistp384"
+_ECDSA_NISTP521 = b"ecdsa-sha2-nistp521"
+_CERT_SUFFIX = b"-cert-v01@openssh.com"
+
+_SSH_PUBKEY_RC = re.compile(br"\A(\S+)[ \t]+(\S+)")
+_SK_MAGIC = b"openssh-key-v1\0"
+_SK_START = b"-----BEGIN OPENSSH PRIVATE KEY-----"
+_SK_END = b"-----END OPENSSH PRIVATE KEY-----"
+_BCRYPT = b"bcrypt"
+_NONE = b"none"
+_DEFAULT_CIPHER = b"aes256-ctr"
+_DEFAULT_ROUNDS = 16
+_MAX_PASSWORD = 72
+
+# re is only way to work on bytes-like data
+_PEM_RC = re.compile(_SK_START + b"(.*?)" + _SK_END, re.DOTALL)
+
+# padding for max blocksize
+_PADDING = memoryview(bytearray(range(1, 1 + 16)))
+
+# ciphers that are actually used in key wrapping
+_SSH_CIPHERS = {
+ b"aes256-ctr": (algorithms.AES, 32, modes.CTR, 16),
+ b"aes256-cbc": (algorithms.AES, 32, modes.CBC, 16),
+}
+
+# map local curve name to key type
+_ECDSA_KEY_TYPE = {
+ "secp256r1": _ECDSA_NISTP256,
+ "secp384r1": _ECDSA_NISTP384,
+ "secp521r1": _ECDSA_NISTP521,
+}
+
+_U32 = struct.Struct(b">I")
+_U64 = struct.Struct(b">Q")
+
+
+def _ecdsa_key_type(public_key):
+ """Return SSH key_type and curve_name for private key."""
+ curve = public_key.curve
+ if curve.name not in _ECDSA_KEY_TYPE:
raise ValueError(
- 'Key header and key body contain different key type values.'
+ "Unsupported curve for ssh private key: %r" % curve.name
)
-
- return loader(key_type, rest, backend)
+ return _ECDSA_KEY_TYPE[curve.name]
-def _load_ssh_rsa_public_key(key_type, decoded_data, backend):
- e, rest = _ssh_read_next_mpint(decoded_data)
- n, rest = _ssh_read_next_mpint(rest)
+def _ssh_pem_encode(data, prefix=_SK_START + b"\n", suffix=_SK_END + b"\n"):
+ return b"".join([prefix, _base64_encode(data), suffix])
- if rest:
- raise ValueError('Key body contains extra bytes.')
- return rsa.RSAPublicNumbers(e, n).public_key(backend)
+def _check_block_size(data, block_len):
+ """Require data to be full blocks"""
+ if not data or len(data) % block_len != 0:
+ raise ValueError("Corrupt data: missing padding")
-def _load_ssh_dss_public_key(key_type, decoded_data, backend):
- p, rest = _ssh_read_next_mpint(decoded_data)
- q, rest = _ssh_read_next_mpint(rest)
- g, rest = _ssh_read_next_mpint(rest)
- y, rest = _ssh_read_next_mpint(rest)
+def _check_empty(data):
+ """All data should have been parsed."""
+ if data:
+ raise ValueError("Corrupt data: unparsed data")
- if rest:
- raise ValueError('Key body contains extra bytes.')
- parameter_numbers = dsa.DSAParameterNumbers(p, q, g)
- public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers)
+def _init_cipher(ciphername, password, salt, rounds, backend):
+ """Generate key + iv and return cipher."""
+ if not password:
+ raise ValueError("Key is password-protected.")
- return public_numbers.public_key(backend)
+ algo, key_len, mode, iv_len = _SSH_CIPHERS[ciphername]
+ seed = _bcrypt_kdf(password, salt, key_len + iv_len, rounds, True)
+ return Cipher(algo(seed[:key_len]), mode(seed[key_len:]), backend)
-def _load_ssh_ecdsa_public_key(expected_key_type, decoded_data, backend):
- curve_name, rest = _ssh_read_next_string(decoded_data)
- data, rest = _ssh_read_next_string(rest)
+def _get_u32(data):
+ """Uint32"""
+ if len(data) < 4:
+ raise ValueError("Invalid data")
+ return _U32.unpack(data[:4])[0], data[4:]
+
+
+def _get_u64(data):
+ """Uint64"""
+ if len(data) < 8:
+ raise ValueError("Invalid data")
+ return _U64.unpack(data[:8])[0], data[8:]
+
+
+def _get_sshstr(data):
+ """Bytes with u32 length prefix"""
+ n, data = _get_u32(data)
+ if n > len(data):
+ raise ValueError("Invalid data")
+ return data[:n], data[n:]
+
+
+def _get_mpint(data):
+ """Big integer."""
+ val, data = _get_sshstr(data)
+ if val and six.indexbytes(val, 0) > 0x7F:
+ raise ValueError("Invalid data")
+ return utils.int_from_bytes(val, "big"), data
+
+
+def _to_mpint(val):
+ """Storage format for signed bigint."""
+ if val < 0:
+ raise ValueError("negative mpint not allowed")
+ if not val:
+ return b""
+ nbytes = (val.bit_length() + 8) // 8
+ return utils.int_to_bytes(val, nbytes)
+
+
+class _FragList(object):
+ """Build recursive structure without data copy."""
+
+ def __init__(self, init=None):
+ self.flist = []
+ if init:
+ self.flist.extend(init)
+
+ def put_raw(self, val):
+ """Add plain bytes"""
+ self.flist.append(val)
+
+ def put_u32(self, val):
+ """Big-endian uint32"""
+ self.flist.append(_U32.pack(val))
+
+ def put_sshstr(self, val):
+ """Bytes prefixed with u32 length"""
+ if isinstance(val, (bytes, memoryview, bytearray)):
+ self.put_u32(len(val))
+ self.flist.append(val)
+ else:
+ self.put_u32(val.size())
+ self.flist.extend(val.flist)
+
+ def put_mpint(self, val):
+ """Big-endian bigint prefixed with u32 length"""
+ self.put_sshstr(_to_mpint(val))
+
+ def size(self):
+ """Current number of bytes"""
+ return sum(map(len, self.flist))
+
+ def render(self, dstbuf, pos=0):
+ """Write into bytearray"""
+ for frag in self.flist:
+ flen = len(frag)
+ start, pos = pos, pos + flen
+ dstbuf[start:pos] = frag
+ return pos
+
+ def tobytes(self):
+ """Return as bytes"""
+ buf = memoryview(bytearray(self.size()))
+ self.render(buf)
+ return buf.tobytes()
+
+
+class _SSHFormatRSA(object):
+ """Format for RSA keys.
+
+ Public:
+ mpint e, n
+ Private:
+ mpint n, e, d, iqmp, p, q
+ """
- if expected_key_type != b"ecdsa-sha2-" + curve_name:
- raise ValueError(
- 'Key header and key body contain different key type values.'
+ def get_public(self, data):
+ """RSA public fields"""
+ e, data = _get_mpint(data)
+ n, data = _get_mpint(data)
+ return (e, n), data
+
+ def load_public(self, key_type, data, backend):
+ """Make RSA public key from data."""
+ (e, n), data = self.get_public(data)
+ public_numbers = rsa.RSAPublicNumbers(e, n)
+ public_key = public_numbers.public_key(backend)
+ return public_key, data
+
+ def load_private(self, data, pubfields, backend):
+ """Make RSA private key from data."""
+ n, data = _get_mpint(data)
+ e, data = _get_mpint(data)
+ d, data = _get_mpint(data)
+ iqmp, data = _get_mpint(data)
+ p, data = _get_mpint(data)
+ q, data = _get_mpint(data)
+
+ if (e, n) != pubfields:
+ raise ValueError("Corrupt data: rsa field mismatch")
+ dmp1 = rsa.rsa_crt_dmp1(d, p)
+ dmq1 = rsa.rsa_crt_dmq1(d, q)
+ public_numbers = rsa.RSAPublicNumbers(e, n)
+ private_numbers = rsa.RSAPrivateNumbers(
+ p, q, d, dmp1, dmq1, iqmp, public_numbers
)
+ private_key = private_numbers.private_key(backend)
+ return private_key, data
- if rest:
- raise ValueError('Key body contains extra bytes.')
+ def encode_public(self, public_key, f_pub):
+ """Write RSA public key"""
+ pubn = public_key.public_numbers()
+ f_pub.put_mpint(pubn.e)
+ f_pub.put_mpint(pubn.n)
- curve = {
- b"nistp256": ec.SECP256R1,
- b"nistp384": ec.SECP384R1,
- b"nistp521": ec.SECP521R1,
- }[curve_name]()
+ def encode_private(self, private_key, f_priv):
+ """Write RSA private key"""
+ private_numbers = private_key.private_numbers()
+ public_numbers = private_numbers.public_numbers
- if six.indexbytes(data, 0) != 4:
- raise NotImplementedError(
- "Compressed elliptic curve points are not supported"
- )
+ f_priv.put_mpint(public_numbers.n)
+ f_priv.put_mpint(public_numbers.e)
+
+ f_priv.put_mpint(private_numbers.d)
+ f_priv.put_mpint(private_numbers.iqmp)
+ f_priv.put_mpint(private_numbers.p)
+ f_priv.put_mpint(private_numbers.q)
- return ec.EllipticCurvePublicKey.from_encoded_point(curve, data)
+class _SSHFormatDSA(object):
+ """Format for DSA keys.
-def _ssh_read_next_string(data):
+ Public:
+ mpint p, q, g, y
+ Private:
+ mpint p, q, g, y, x
"""
- Retrieves the next RFC 4251 string value from the data.
- While the RFC calls these strings, in Python they are bytes objects.
+ def get_public(self, data):
+ """DSA public fields"""
+ p, data = _get_mpint(data)
+ q, data = _get_mpint(data)
+ g, data = _get_mpint(data)
+ y, data = _get_mpint(data)
+ return (p, q, g, y), data
+
+ def load_public(self, key_type, data, backend):
+ """Make DSA public key from data."""
+ (p, q, g, y), data = self.get_public(data)
+ parameter_numbers = dsa.DSAParameterNumbers(p, q, g)
+ public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers)
+ self._validate(public_numbers)
+ public_key = public_numbers.public_key(backend)
+ return public_key, data
+
+ def load_private(self, data, pubfields, backend):
+ """Make DSA private key from data."""
+ (p, q, g, y), data = self.get_public(data)
+ x, data = _get_mpint(data)
+
+ if (p, q, g, y) != pubfields:
+ raise ValueError("Corrupt data: dsa field mismatch")
+ parameter_numbers = dsa.DSAParameterNumbers(p, q, g)
+ public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers)
+ self._validate(public_numbers)
+ private_numbers = dsa.DSAPrivateNumbers(x, public_numbers)
+ private_key = private_numbers.private_key(backend)
+ return private_key, data
+
+ def encode_public(self, public_key, f_pub):
+ """Write DSA public key"""
+ public_numbers = public_key.public_numbers()
+ parameter_numbers = public_numbers.parameter_numbers
+ self._validate(public_numbers)
+
+ f_pub.put_mpint(parameter_numbers.p)
+ f_pub.put_mpint(parameter_numbers.q)
+ f_pub.put_mpint(parameter_numbers.g)
+ f_pub.put_mpint(public_numbers.y)
+
+ def encode_private(self, private_key, f_priv):
+ """Write DSA private key"""
+ self.encode_public(private_key.public_key(), f_priv)
+ f_priv.put_mpint(private_key.private_numbers().x)
+
+ def _validate(self, public_numbers):
+ parameter_numbers = public_numbers.parameter_numbers
+ if parameter_numbers.p.bit_length() != 1024:
+ raise ValueError("SSH supports only 1024 bit DSA keys")
+
+
+class _SSHFormatECDSA(object):
+ """Format for ECDSA keys.
+
+ Public:
+ str curve
+ bytes point
+ Private:
+ str curve
+ bytes point
+ mpint secret
"""
- if len(data) < 4:
- raise ValueError("Key is not in the proper format")
- str_len, = struct.unpack('>I', data[:4])
- if len(data) < str_len + 4:
- raise ValueError("Key is not in the proper format")
+ def __init__(self, ssh_curve_name, curve):
+ self.ssh_curve_name = ssh_curve_name
+ self.curve = curve
+
+ def get_public(self, data):
+ """ECDSA public fields"""
+ curve, data = _get_sshstr(data)
+ point, data = _get_sshstr(data)
+ if curve != self.ssh_curve_name:
+ raise ValueError("Curve name mismatch")
+ if six.indexbytes(point, 0) != 4:
+ raise NotImplementedError("Need uncompressed point")
+ return (curve, point), data
+
+ def load_public(self, key_type, data, backend):
+ """Make ECDSA public key from data."""
+ (curve_name, point), data = self.get_public(data)
+ public_key = ec.EllipticCurvePublicKey.from_encoded_point(
+ self.curve, point.tobytes()
+ )
+ return public_key, data
+
+ def load_private(self, data, pubfields, backend):
+ """Make ECDSA private key from data."""
+ (curve_name, point), data = self.get_public(data)
+ secret, data = _get_mpint(data)
+
+ if (curve_name, point) != pubfields:
+ raise ValueError("Corrupt data: ecdsa field mismatch")
+ private_key = ec.derive_private_key(secret, self.curve, backend)
+ return private_key, data
+
+ def encode_public(self, public_key, f_pub):
+ """Write ECDSA public key"""
+ point = public_key.public_bytes(
+ Encoding.X962, PublicFormat.UncompressedPoint
+ )
+ f_pub.put_sshstr(self.ssh_curve_name)
+ f_pub.put_sshstr(point)
- return data[4:4 + str_len], data[4 + str_len:]
+ def encode_private(self, private_key, f_priv):
+ """Write ECDSA private key"""
+ public_key = private_key.public_key()
+ private_numbers = private_key.private_numbers()
+ self.encode_public(public_key, f_priv)
+ f_priv.put_mpint(private_numbers.private_value)
-def _ssh_read_next_mpint(data):
- """
- Reads the next mpint from the data.
- Currently, all mpints are interpreted as unsigned.
+class _SSHFormatEd25519(object):
+ """Format for Ed25519 keys.
+
+ Public:
+ bytes point
+ Private:
+ bytes point
+ bytes secret_and_point
"""
- mpint_data, rest = _ssh_read_next_string(data)
- return (
- utils.int_from_bytes(mpint_data, byteorder='big', signed=False), rest
- )
+ def get_public(self, data):
+ """Ed25519 public fields"""
+ point, data = _get_sshstr(data)
+ return (point,), data
+ def load_public(self, key_type, data, backend):
+ """Make Ed25519 public key from data."""
+ (point,), data = self.get_public(data)
+ public_key = ed25519.Ed25519PublicKey.from_public_bytes(
+ point.tobytes()
+ )
+ return public_key, data
+
+ def load_private(self, data, pubfields, backend):
+ """Make Ed25519 private key from data."""
+ (point,), data = self.get_public(data)
+ keypair, data = _get_sshstr(data)
+
+ secret = keypair[:32]
+ point2 = keypair[32:]
+ if point != point2 or (point,) != pubfields:
+ raise ValueError("Corrupt data: ed25519 field mismatch")
+ private_key = ed25519.Ed25519PrivateKey.from_private_bytes(secret)
+ return private_key, data
+
+ def encode_public(self, public_key, f_pub):
+ """Write Ed25519 public key"""
+ raw_public_key = public_key.public_bytes(
+ Encoding.Raw, PublicFormat.Raw
+ )
+ f_pub.put_sshstr(raw_public_key)
-def _ssh_write_string(data):
- return struct.pack(">I", len(data)) + data
+ def encode_private(self, private_key, f_priv):
+ """Write Ed25519 private key"""
+ public_key = private_key.public_key()
+ raw_private_key = private_key.private_bytes(
+ Encoding.Raw, PrivateFormat.Raw, NoEncryption()
+ )
+ raw_public_key = public_key.public_bytes(
+ Encoding.Raw, PublicFormat.Raw
+ )
+ f_keypair = _FragList([raw_private_key, raw_public_key])
+
+ self.encode_public(public_key, f_priv)
+ f_priv.put_sshstr(f_keypair)
+
+
+_KEY_FORMATS = {
+ _SSH_RSA: _SSHFormatRSA(),
+ _SSH_DSA: _SSHFormatDSA(),
+ _SSH_ED25519: _SSHFormatEd25519(),
+ _ECDSA_NISTP256: _SSHFormatECDSA(b"nistp256", ec.SECP256R1()),
+ _ECDSA_NISTP384: _SSHFormatECDSA(b"nistp384", ec.SECP384R1()),
+ _ECDSA_NISTP521: _SSHFormatECDSA(b"nistp521", ec.SECP521R1()),
+}
+
+
+def _lookup_kformat(key_type):
+ """Return valid format or throw error"""
+ if not isinstance(key_type, bytes):
+ key_type = memoryview(key_type).tobytes()
+ if key_type in _KEY_FORMATS:
+ return _KEY_FORMATS[key_type]
+ raise UnsupportedAlgorithm("Unsupported key type: %r" % key_type)
+
+
+def load_ssh_private_key(data, password, backend=None):
+ """Load private key from OpenSSH custom encoding."""
+ utils._check_byteslike("data", data)
+ backend = _get_backend(backend)
+ if password is not None:
+ utils._check_bytes("password", password)
+
+ m = _PEM_RC.search(data)
+ if not m:
+ raise ValueError("Not OpenSSH private key format")
+ p1 = m.start(1)
+ p2 = m.end(1)
+ data = binascii.a2b_base64(memoryview(data)[p1:p2])
+ if not data.startswith(_SK_MAGIC):
+ raise ValueError("Not OpenSSH private key format")
+ data = memoryview(data)[len(_SK_MAGIC) :]
+
+ # parse header
+ ciphername, data = _get_sshstr(data)
+ kdfname, data = _get_sshstr(data)
+ kdfoptions, data = _get_sshstr(data)
+ nkeys, data = _get_u32(data)
+ if nkeys != 1:
+ raise ValueError("Only one key supported")
+
+ # load public key data
+ pubdata, data = _get_sshstr(data)
+ pub_key_type, pubdata = _get_sshstr(pubdata)
+ kformat = _lookup_kformat(pub_key_type)
+ pubfields, pubdata = kformat.get_public(pubdata)
+ _check_empty(pubdata)
+
+ # load secret data
+ edata, data = _get_sshstr(data)
+ _check_empty(data)
+
+ if (ciphername, kdfname) != (_NONE, _NONE):
+ ciphername = ciphername.tobytes()
+ if ciphername not in _SSH_CIPHERS:
+ raise UnsupportedAlgorithm("Unsupported cipher: %r" % ciphername)
+ if kdfname != _BCRYPT:
+ raise UnsupportedAlgorithm("Unsupported KDF: %r" % kdfname)
+ blklen = _SSH_CIPHERS[ciphername][3]
+ _check_block_size(edata, blklen)
+ salt, kbuf = _get_sshstr(kdfoptions)
+ rounds, kbuf = _get_u32(kbuf)
+ _check_empty(kbuf)
+ ciph = _init_cipher(
+ ciphername, password, salt.tobytes(), rounds, backend
+ )
+ edata = memoryview(ciph.decryptor().update(edata))
+ else:
+ blklen = 8
+ _check_block_size(edata, blklen)
+ ck1, edata = _get_u32(edata)
+ ck2, edata = _get_u32(edata)
+ if ck1 != ck2:
+ raise ValueError("Corrupt data: broken checksum")
+
+ # load per-key struct
+ key_type, edata = _get_sshstr(edata)
+ if key_type != pub_key_type:
+ raise ValueError("Corrupt data: key type mismatch")
+ private_key, edata = kformat.load_private(edata, pubfields, backend)
+ comment, edata = _get_sshstr(edata)
+
+ # yes, SSH does padding check *after* all other parsing is done.
+ # need to follow as it writes zero-byte padding too.
+ if edata != _PADDING[: len(edata)]:
+ raise ValueError("Corrupt data: invalid padding")
+
+ return private_key
+
+
+def serialize_ssh_private_key(private_key, password=None):
+ """Serialize private key with OpenSSH custom encoding."""
+ if password is not None:
+ utils._check_bytes("password", password)
+ if password and len(password) > _MAX_PASSWORD:
+ raise ValueError(
+ "Passwords longer than 72 bytes are not supported by "
+ "OpenSSH private key format"
+ )
+
+ if isinstance(private_key, ec.EllipticCurvePrivateKey):
+ key_type = _ecdsa_key_type(private_key.public_key())
+ elif isinstance(private_key, rsa.RSAPrivateKey):
+ key_type = _SSH_RSA
+ elif isinstance(private_key, dsa.DSAPrivateKey):
+ key_type = _SSH_DSA
+ elif isinstance(private_key, ed25519.Ed25519PrivateKey):
+ key_type = _SSH_ED25519
+ else:
+ raise ValueError("Unsupported key type")
+ kformat = _lookup_kformat(key_type)
+
+ # setup parameters
+ f_kdfoptions = _FragList()
+ if password:
+ ciphername = _DEFAULT_CIPHER
+ blklen = _SSH_CIPHERS[ciphername][3]
+ kdfname = _BCRYPT
+ rounds = _DEFAULT_ROUNDS
+ salt = os.urandom(16)
+ f_kdfoptions.put_sshstr(salt)
+ f_kdfoptions.put_u32(rounds)
+ backend = _get_backend(None)
+ ciph = _init_cipher(ciphername, password, salt, rounds, backend)
+ else:
+ ciphername = kdfname = _NONE
+ blklen = 8
+ ciph = None
+ nkeys = 1
+ checkval = os.urandom(4)
+ comment = b""
+
+ # encode public and private parts together
+ f_public_key = _FragList()
+ f_public_key.put_sshstr(key_type)
+ kformat.encode_public(private_key.public_key(), f_public_key)
+
+ f_secrets = _FragList([checkval, checkval])
+ f_secrets.put_sshstr(key_type)
+ kformat.encode_private(private_key, f_secrets)
+ f_secrets.put_sshstr(comment)
+ f_secrets.put_raw(_PADDING[: blklen - (f_secrets.size() % blklen)])
+
+ # top-level structure
+ f_main = _FragList()
+ f_main.put_raw(_SK_MAGIC)
+ f_main.put_sshstr(ciphername)
+ f_main.put_sshstr(kdfname)
+ f_main.put_sshstr(f_kdfoptions)
+ f_main.put_u32(nkeys)
+ f_main.put_sshstr(f_public_key)
+ f_main.put_sshstr(f_secrets)
+
+ # copy result info bytearray
+ slen = f_secrets.size()
+ mlen = f_main.size()
+ buf = memoryview(bytearray(mlen + blklen))
+ f_main.render(buf)
+ ofs = mlen - slen
+
+ # encrypt in-place
+ if ciph is not None:
+ ciph.encryptor().update_into(buf[ofs:mlen], buf[ofs:])
+
+ txt = _ssh_pem_encode(buf[:mlen])
+ buf[ofs:mlen] = bytearray(slen)
+ return txt
+
+
+def load_ssh_public_key(data, backend=None):
+ """Load public key from OpenSSH one-line format."""
+ backend = _get_backend(backend)
+ utils._check_byteslike("data", data)
+
+ m = _SSH_PUBKEY_RC.match(data)
+ if not m:
+ raise ValueError("Invalid line format")
+ key_type = orig_key_type = m.group(1)
+ key_body = m.group(2)
+ with_cert = False
+ if _CERT_SUFFIX == key_type[-len(_CERT_SUFFIX) :]:
+ with_cert = True
+ key_type = key_type[: -len(_CERT_SUFFIX)]
+ kformat = _lookup_kformat(key_type)
+
+ try:
+ data = memoryview(binascii.a2b_base64(key_body))
+ except (TypeError, binascii.Error):
+ raise ValueError("Invalid key format")
+
+ inner_key_type, data = _get_sshstr(data)
+ if inner_key_type != orig_key_type:
+ raise ValueError("Invalid key format")
+ if with_cert:
+ nonce, data = _get_sshstr(data)
+ public_key, data = kformat.load_public(key_type, data, backend)
+ if with_cert:
+ serial, data = _get_u64(data)
+ cctype, data = _get_u32(data)
+ key_id, data = _get_sshstr(data)
+ principals, data = _get_sshstr(data)
+ valid_after, data = _get_u64(data)
+ valid_before, data = _get_u64(data)
+ crit_options, data = _get_sshstr(data)
+ extensions, data = _get_sshstr(data)
+ reserved, data = _get_sshstr(data)
+ sig_key, data = _get_sshstr(data)
+ signature, data = _get_sshstr(data)
+ _check_empty(data)
+ return public_key
+
+
+def serialize_ssh_public_key(public_key):
+ """One-line public key format for OpenSSH"""
+ if isinstance(public_key, ec.EllipticCurvePublicKey):
+ key_type = _ecdsa_key_type(public_key)
+ elif isinstance(public_key, rsa.RSAPublicKey):
+ key_type = _SSH_RSA
+ elif isinstance(public_key, dsa.DSAPublicKey):
+ key_type = _SSH_DSA
+ elif isinstance(public_key, ed25519.Ed25519PublicKey):
+ key_type = _SSH_ED25519
+ else:
+ raise ValueError("Unsupported key type")
+ kformat = _lookup_kformat(key_type)
+ f_pub = _FragList()
+ f_pub.put_sshstr(key_type)
+ kformat.encode_public(public_key, f_pub)
-def _ssh_write_mpint(value):
- data = utils.int_to_bytes(value)
- if six.indexbytes(data, 0) & 0x80:
- data = b"\x00" + data
- return _ssh_write_string(data)
+ pub = binascii.b2a_base64(f_pub.tobytes()).strip()
+ return b"".join([key_type, b" ", pub])
diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py
index 4ad1bdc2f..c00eec0e5 100644
--- a/src/cryptography/hazmat/primitives/twofactor/hotp.py
+++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py
@@ -8,9 +8,8 @@ import struct
import six
-from cryptography.exceptions import (
- UnsupportedAlgorithm, _Reasons
-)
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time, hmac
from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512
@@ -19,12 +18,14 @@ from cryptography.hazmat.primitives.twofactor.utils import _generate_uri
class HOTP(object):
- def __init__(self, key, length, algorithm, backend,
- enforce_key_length=True):
+ def __init__(
+ self, key, length, algorithm, backend=None, enforce_key_length=True
+ ):
+ backend = _get_backend(backend)
if not isinstance(backend, HMACBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HMACBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
if len(key) < 16 and enforce_key_length is True:
@@ -59,10 +60,10 @@ class HOTP(object):
hmac_value = ctx.finalize()
offset = six.indexbytes(hmac_value, len(hmac_value) - 1) & 0b1111
- p = hmac_value[offset:offset + 4]
- return struct.unpack(">I", p)[0] & 0x7fffffff
+ p = hmac_value[offset : offset + 4]
+ return struct.unpack(">I", p)[0] & 0x7FFFFFFF
def get_provisioning_uri(self, account_name, counter, issuer):
- return _generate_uri(self, "hotp", account_name, issuer, [
- ("counter", int(counter)),
- ])
+ return _generate_uri(
+ self, "hotp", account_name, issuer, [("counter", int(counter))]
+ )
diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py
index 499f2824a..d59539b3f 100644
--- a/src/cryptography/hazmat/primitives/twofactor/totp.py
+++ b/src/cryptography/hazmat/primitives/twofactor/totp.py
@@ -4,9 +4,8 @@
from __future__ import absolute_import, division, print_function
-from cryptography.exceptions import (
- UnsupportedAlgorithm, _Reasons
-)
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+from cryptography.hazmat.backends import _get_backend
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time
from cryptography.hazmat.primitives.twofactor import InvalidToken
@@ -15,12 +14,20 @@ from cryptography.hazmat.primitives.twofactor.utils import _generate_uri
class TOTP(object):
- def __init__(self, key, length, algorithm, time_step, backend,
- enforce_key_length=True):
+ def __init__(
+ self,
+ key,
+ length,
+ algorithm,
+ time_step,
+ backend=None,
+ enforce_key_length=True,
+ ):
+ backend = _get_backend(backend)
if not isinstance(backend, HMACBackend):
raise UnsupportedAlgorithm(
"Backend object does not implement HMACBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE
+ _Reasons.BACKEND_MISSING_INTERFACE,
)
self._time_step = time_step
@@ -35,6 +42,10 @@ class TOTP(object):
raise InvalidToken("Supplied TOTP value does not match.")
def get_provisioning_uri(self, account_name, issuer):
- return _generate_uri(self._hotp, "totp", account_name, issuer, [
- ("period", int(self._time_step)),
- ])
+ return _generate_uri(
+ self._hotp,
+ "totp",
+ account_name,
+ issuer,
+ [("period", int(self._time_step))],
+ )
diff --git a/src/cryptography/hazmat/primitives/twofactor/utils.py b/src/cryptography/hazmat/primitives/twofactor/utils.py
index 0ed8c4c89..0afa1ccc0 100644
--- a/src/cryptography/hazmat/primitives/twofactor/utils.py
+++ b/src/cryptography/hazmat/primitives/twofactor/utils.py
@@ -23,8 +23,11 @@ def _generate_uri(hotp, type_name, account_name, issuer, extra_parameters):
uriparts = {
"type": type_name,
- "label": ("%s:%s" % (quote(issuer), quote(account_name)) if issuer
- else quote(account_name)),
+ "label": (
+ "%s:%s" % (quote(issuer), quote(account_name))
+ if issuer
+ else quote(account_name)
+ ),
"parameters": urlencode(parameters),
}
return "otpauth://{type}/{label}?{parameters}".format(**uriparts)
diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py
index cbbae3a79..bdb3dbf47 100644
--- a/src/cryptography/utils.py
+++ b/src/cryptography/utils.py
@@ -20,22 +20,20 @@ class CryptographyDeprecationWarning(UserWarning):
# Several APIs were deprecated with no specific end-of-life date because of the
# ubiquity of their use. They should not be removed until we agree on when that
# cycle ends.
-PersistentlyDeprecated = CryptographyDeprecationWarning
-DeprecatedIn21 = CryptographyDeprecationWarning
-DeprecatedIn23 = CryptographyDeprecationWarning
-DeprecatedIn25 = CryptographyDeprecationWarning
+PersistentlyDeprecated2017 = CryptographyDeprecationWarning
+PersistentlyDeprecated2019 = CryptographyDeprecationWarning
def _check_bytes(name, value):
if not isinstance(value, bytes):
- raise TypeError("{0} must be bytes".format(name))
+ raise TypeError("{} must be bytes".format(name))
def _check_byteslike(name, value):
try:
memoryview(value)
except TypeError:
- raise TypeError("{0} must be bytes-like".format(name))
+ raise TypeError("{} must be bytes-like".format(name))
def read_only_property(name):
@@ -47,6 +45,7 @@ def register_interface(iface):
verify_interface(iface, klass)
iface.register(klass)
return klass
+
return register_decorator
@@ -56,27 +55,33 @@ def register_interface_if(predicate, iface):
verify_interface(iface, klass)
iface.register(klass)
return klass
+
return register_decorator
if hasattr(int, "from_bytes"):
int_from_bytes = int.from_bytes
else:
+
def int_from_bytes(data, byteorder, signed=False):
- assert byteorder == 'big'
+ assert byteorder == "big"
assert not signed
return int(binascii.hexlify(data), 16)
if hasattr(int, "to_bytes"):
+
def int_to_bytes(integer, length=None):
return integer.to_bytes(
- length or (integer.bit_length() + 7) // 8 or 1, 'big'
+ length or (integer.bit_length() + 7) // 8 or 1, "big"
)
+
+
else:
+
def int_to_bytes(integer, length=None):
- hex_string = '%x' % integer
+ hex_string = "%x" % integer
if length is None:
n = len(hex_string)
else:
@@ -98,7 +103,7 @@ def verify_interface(iface, klass):
for method in iface.__abstractmethods__:
if not hasattr(klass, method):
raise InterfaceNotImplemented(
- "{0} is missing a {1!r} method".format(klass, method)
+ "{} is missing a {!r} method".format(klass, method)
)
if isinstance(getattr(iface, method), abc.abstractproperty):
# Can't properly verify these yet.
@@ -107,19 +112,11 @@ def verify_interface(iface, klass):
actual = signature(getattr(klass, method))
if sig != actual:
raise InterfaceNotImplemented(
- "{0}.{1}'s signature differs from the expected. Expected: "
- "{2!r}. Received: {3!r}".format(
- klass, method, sig, actual
- )
+ "{}.{}'s signature differs from the expected. Expected: "
+ "{!r}. Received: {!r}".format(klass, method, sig, actual)
)
-# No longer needed as of 2.2, but retained because we have external consumers
-# who use it.
-def bit_length(x):
- return x.bit_length()
-
-
class _DeprecatedValue(object):
def __init__(self, value, message, warning_class):
self.value = value
@@ -160,7 +157,7 @@ def deprecated(value, module_name, message, warning_class):
def cached_property(func):
- cached_name = "_cached_{0}".format(func)
+ cached_name = "_cached_{}".format(func)
sentinel = object()
def inner(instance):
@@ -170,4 +167,5 @@ def cached_property(func):
result = func(instance)
setattr(instance, cached_name, result)
return result
+
return property(inner)
diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py
index b761e264a..69630e4cb 100644
--- a/src/cryptography/x509/__init__.py
+++ b/src/cryptography/x509/__init__.py
@@ -6,39 +6,95 @@ from __future__ import absolute_import, division, print_function
from cryptography.x509 import certificate_transparency
from cryptography.x509.base import (
- Certificate, CertificateBuilder, CertificateRevocationList,
+ AttributeNotFound,
+ Certificate,
+ CertificateBuilder,
+ CertificateRevocationList,
CertificateRevocationListBuilder,
- CertificateSigningRequest, CertificateSigningRequestBuilder,
- InvalidVersion, RevokedCertificate, RevokedCertificateBuilder,
- Version, load_der_x509_certificate, load_der_x509_crl, load_der_x509_csr,
- load_pem_x509_certificate, load_pem_x509_crl, load_pem_x509_csr,
+ CertificateSigningRequest,
+ CertificateSigningRequestBuilder,
+ InvalidVersion,
+ RevokedCertificate,
+ RevokedCertificateBuilder,
+ Version,
+ load_der_x509_certificate,
+ load_der_x509_crl,
+ load_der_x509_csr,
+ load_pem_x509_certificate,
+ load_pem_x509_crl,
+ load_pem_x509_csr,
random_serial_number,
)
from cryptography.x509.extensions import (
- AccessDescription, AuthorityInformationAccess,
- AuthorityKeyIdentifier, BasicConstraints, CRLDistributionPoints,
- CRLNumber, CRLReason, CertificateIssuer, CertificatePolicies,
- DeltaCRLIndicator, DistributionPoint, DuplicateExtension, ExtendedKeyUsage,
- Extension, ExtensionNotFound, ExtensionType, Extensions, FreshestCRL,
- GeneralNames, InhibitAnyPolicy, InvalidityDate, IssuerAlternativeName,
- IssuingDistributionPoint, KeyUsage, NameConstraints, NoticeReference,
- OCSPNoCheck, OCSPNonce, PolicyConstraints, PolicyInformation,
- PrecertPoison, PrecertificateSignedCertificateTimestamps, ReasonFlags,
- SubjectAlternativeName, SubjectKeyIdentifier, TLSFeature, TLSFeatureType,
- UnrecognizedExtension, UserNotice
+ AccessDescription,
+ AuthorityInformationAccess,
+ AuthorityKeyIdentifier,
+ BasicConstraints,
+ CRLDistributionPoints,
+ CRLNumber,
+ CRLReason,
+ CertificateIssuer,
+ CertificatePolicies,
+ DeltaCRLIndicator,
+ DistributionPoint,
+ DuplicateExtension,
+ ExtendedKeyUsage,
+ Extension,
+ ExtensionNotFound,
+ ExtensionType,
+ Extensions,
+ FreshestCRL,
+ GeneralNames,
+ InhibitAnyPolicy,
+ InvalidityDate,
+ IssuerAlternativeName,
+ IssuingDistributionPoint,
+ KeyUsage,
+ NameConstraints,
+ NoticeReference,
+ OCSPNoCheck,
+ OCSPNonce,
+ PolicyConstraints,
+ PolicyInformation,
+ PrecertPoison,
+ PrecertificateSignedCertificateTimestamps,
+ ReasonFlags,
+ SignedCertificateTimestamps,
+ SubjectAlternativeName,
+ SubjectInformationAccess,
+ SubjectKeyIdentifier,
+ TLSFeature,
+ TLSFeatureType,
+ UnrecognizedExtension,
+ UserNotice,
)
from cryptography.x509.general_name import (
- DNSName, DirectoryName, GeneralName, IPAddress, OtherName, RFC822Name,
- RegisteredID, UniformResourceIdentifier, UnsupportedGeneralNameType,
- _GENERAL_NAMES
+ DNSName,
+ DirectoryName,
+ GeneralName,
+ IPAddress,
+ OtherName,
+ RFC822Name,
+ RegisteredID,
+ UniformResourceIdentifier,
+ UnsupportedGeneralNameType,
+ _GENERAL_NAMES,
)
from cryptography.x509.name import (
- Name, NameAttribute, RelativeDistinguishedName
+ Name,
+ NameAttribute,
+ RelativeDistinguishedName,
)
from cryptography.x509.oid import (
- AuthorityInformationAccessOID, CRLEntryExtensionOID,
- CertificatePoliciesOID, ExtendedKeyUsageOID, ExtensionOID, NameOID,
- ObjectIdentifier, SignatureAlgorithmOID, _SIG_OIDS_TO_HASH
+ AuthorityInformationAccessOID,
+ CRLEntryExtensionOID,
+ CertificatePoliciesOID,
+ ExtendedKeyUsageOID,
+ ExtensionOID,
+ NameOID,
+ ObjectIdentifier,
+ SignatureAlgorithmOID,
+ _SIG_OIDS_TO_HASH,
)
@@ -120,6 +176,7 @@ __all__ = [
"load_pem_x509_crl",
"load_der_x509_crl",
"random_serial_number",
+ "AttributeNotFound",
"InvalidVersion",
"DeltaCRLIndicator",
"DuplicateExtension",
@@ -142,6 +199,7 @@ __all__ = [
"CRLNumber",
"KeyUsage",
"AuthorityInformationAccess",
+ "SubjectInformationAccess",
"AccessDescription",
"CertificatePolicies",
"PolicyInformation",
@@ -186,4 +244,5 @@ __all__ = [
"PrecertificateSignedCertificateTimestamps",
"PrecertPoison",
"OCSPNonce",
+ "SignedCertificateTimestamps",
]
diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py
index 63c2e3c63..f3bc872b9 100644
--- a/src/cryptography/x509/base.py
+++ b/src/cryptography/x509/base.py
@@ -12,19 +12,40 @@ from enum import Enum
import six
from cryptography import utils
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
+from cryptography.hazmat.backends import _get_backend
+from cryptography.hazmat.primitives.asymmetric import (
+ dsa,
+ ec,
+ ed25519,
+ ed448,
+ rsa,
+)
from cryptography.x509.extensions import Extension, ExtensionType
from cryptography.x509.name import Name
+from cryptography.x509.oid import ObjectIdentifier
_EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1)
+class AttributeNotFound(Exception):
+ def __init__(self, msg, oid):
+ super(AttributeNotFound, self).__init__(msg)
+ self.oid = oid
+
+
def _reject_duplicate_extension(extension, extensions):
# This is quadratic in the number of extensions
for e in extensions:
if e.oid == extension.oid:
- raise ValueError('This extension has already been set.')
+ raise ValueError("This extension has already been set.")
+
+
+def _reject_duplicate_attribute(oid, attributes):
+ # This is quadratic in the number of attributes
+ for attr_oid, _ in attributes:
+ if attr_oid == oid:
+ raise ValueError("This attribute has already been set.")
def _convert_to_naive_utc_time(time):
@@ -46,27 +67,33 @@ class Version(Enum):
v3 = 2
-def load_pem_x509_certificate(data, backend):
+def load_pem_x509_certificate(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_pem_x509_certificate(data)
-def load_der_x509_certificate(data, backend):
+def load_der_x509_certificate(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_der_x509_certificate(data)
-def load_pem_x509_csr(data, backend):
+def load_pem_x509_csr(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_pem_x509_csr(data)
-def load_der_x509_csr(data, backend):
+def load_der_x509_csr(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_der_x509_csr(data)
-def load_pem_x509_crl(data, backend):
+def load_pem_x509_crl(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_pem_x509_crl(data)
-def load_der_x509_crl(data, backend):
+def load_der_x509_crl(data, backend=None):
+ backend = _get_backend(backend)
return backend.load_der_x509_crl(data)
@@ -365,6 +392,12 @@ class CertificateSigningRequest(object):
Verifies signature of signing request.
"""
+ @abc.abstractproperty
+ def get_attribute_for_oid(self):
+ """
+ Get the attribute value for a given OID.
+ """
+
@six.add_metaclass(abc.ABCMeta)
class RevokedCertificate(object):
@@ -388,22 +421,25 @@ class RevokedCertificate(object):
class CertificateSigningRequestBuilder(object):
- def __init__(self, subject_name=None, extensions=[]):
+ def __init__(self, subject_name=None, extensions=[], attributes=[]):
"""
Creates an empty X.509 certificate request (v1).
"""
self._subject_name = subject_name
self._extensions = extensions
+ self._attributes = attributes
def subject_name(self, name):
"""
Sets the certificate requestor's distinguished name.
"""
if not isinstance(name, Name):
- raise TypeError('Expecting x509.Name object.')
+ raise TypeError("Expecting x509.Name object.")
if self._subject_name is not None:
- raise ValueError('The subject name may only be set once.')
- return CertificateSigningRequestBuilder(name, self._extensions)
+ raise ValueError("The subject name may only be set once.")
+ return CertificateSigningRequestBuilder(
+ name, self._extensions, self._attributes
+ )
def add_extension(self, extension, critical):
"""
@@ -416,22 +452,50 @@ class CertificateSigningRequestBuilder(object):
_reject_duplicate_extension(extension, self._extensions)
return CertificateSigningRequestBuilder(
- self._subject_name, self._extensions + [extension]
+ self._subject_name,
+ self._extensions + [extension],
+ self._attributes,
)
- def sign(self, private_key, algorithm, backend):
+ def add_attribute(self, oid, value):
+ """
+ Adds an X.509 attribute with an OID and associated value.
+ """
+ if not isinstance(oid, ObjectIdentifier):
+ raise TypeError("oid must be an ObjectIdentifier")
+
+ if not isinstance(value, bytes):
+ raise TypeError("value must be bytes")
+
+ _reject_duplicate_attribute(oid, self._attributes)
+
+ return CertificateSigningRequestBuilder(
+ self._subject_name,
+ self._extensions,
+ self._attributes + [(oid, value)],
+ )
+
+ def sign(self, private_key, algorithm, backend=None):
"""
Signs the request using the requestor's private key.
"""
+ backend = _get_backend(backend)
if self._subject_name is None:
raise ValueError("A CertificateSigningRequest must have a subject")
return backend.create_x509_csr(self, private_key, algorithm)
class CertificateBuilder(object):
- def __init__(self, issuer_name=None, subject_name=None,
- public_key=None, serial_number=None, not_valid_before=None,
- not_valid_after=None, extensions=[]):
+ def __init__(
+ self,
+ issuer_name=None,
+ subject_name=None,
+ public_key=None,
+ serial_number=None,
+ not_valid_before=None,
+ not_valid_after=None,
+ extensions=[],
+ ):
self._version = Version.v3
self._issuer_name = issuer_name
self._subject_name = subject_name
@@ -446,13 +510,17 @@ class CertificateBuilder(object):
Sets the CA's distinguished name.
"""
if not isinstance(name, Name):
- raise TypeError('Expecting x509.Name object.')
+ raise TypeError("Expecting x509.Name object.")
if self._issuer_name is not None:
- raise ValueError('The issuer name may only be set once.')
+ raise ValueError("The issuer name may only be set once.")
return CertificateBuilder(
- name, self._subject_name, self._public_key,
- self._serial_number, self._not_valid_before,
- self._not_valid_after, self._extensions
+ name,
+ self._subject_name,
+ self._public_key,
+ self._serial_number,
+ self._not_valid_before,
+ self._not_valid_after,
+ self._extensions,
)
def subject_name(self, name):
@@ -460,29 +528,48 @@ class CertificateBuilder(object):
Sets the requestor's distinguished name.
"""
if not isinstance(name, Name):
- raise TypeError('Expecting x509.Name object.')
+ raise TypeError("Expecting x509.Name object.")
if self._subject_name is not None:
- raise ValueError('The subject name may only be set once.')
+ raise ValueError("The subject name may only be set once.")
return CertificateBuilder(
- self._issuer_name, name, self._public_key,
- self._serial_number, self._not_valid_before,
- self._not_valid_after, self._extensions
+ self._issuer_name,
+ name,
+ self._public_key,
+ self._serial_number,
+ self._not_valid_before,
+ self._not_valid_after,
+ self._extensions,
)
def public_key(self, key):
"""
Sets the requestor's public key (as found in the signing request).
"""
- if not isinstance(key, (dsa.DSAPublicKey, rsa.RSAPublicKey,
- ec.EllipticCurvePublicKey)):
- raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,'
- ' or EllipticCurvePublicKey.')
+ if not isinstance(
+ key,
+ (
+ dsa.DSAPublicKey,
+ rsa.RSAPublicKey,
+ ec.EllipticCurvePublicKey,
+ ed25519.Ed25519PublicKey,
+ ed448.Ed448PublicKey,
+ ),
+ ):
+ raise TypeError(
+ "Expecting one of DSAPublicKey, RSAPublicKey,"
+ " EllipticCurvePublicKey, Ed25519PublicKey or"
+ " Ed448PublicKey."
+ )
if self._public_key is not None:
- raise ValueError('The public key may only be set once.')
+ raise ValueError("The public key may only be set once.")
return CertificateBuilder(
- self._issuer_name, self._subject_name, key,
- self._serial_number, self._not_valid_before,
- self._not_valid_after, self._extensions
+ self._issuer_name,
+ self._subject_name,
+ key,
+ self._serial_number,
+ self._not_valid_before,
+ self._not_valid_after,
+ self._extensions,
)
def serial_number(self, number):
@@ -490,21 +577,26 @@ class CertificateBuilder(object):
Sets the certificate serial number.
"""
if not isinstance(number, six.integer_types):
- raise TypeError('Serial number must be of integral type.')
+ raise TypeError("Serial number must be of integral type.")
if self._serial_number is not None:
- raise ValueError('The serial number may only be set once.')
+ raise ValueError("The serial number may only be set once.")
if number <= 0:
- raise ValueError('The serial number should be positive.')
+ raise ValueError("The serial number should be positive.")
# ASN.1 integers are always signed, so most significant bit must be
# zero.
if number.bit_length() >= 160: # As defined in RFC 5280
- raise ValueError('The serial number should not be more than 159 '
- 'bits.')
+ raise ValueError(
+ "The serial number should not be more than 159 " "bits."
+ )
return CertificateBuilder(
- self._issuer_name, self._subject_name,
- self._public_key, number, self._not_valid_before,
- self._not_valid_after, self._extensions
+ self._issuer_name,
+ self._subject_name,
+ self._public_key,
+ number,
+ self._not_valid_before,
+ self._not_valid_after,
+ self._extensions,
)
def not_valid_before(self, time):
@@ -512,22 +604,28 @@ class CertificateBuilder(object):
Sets the certificate activation time.
"""
if not isinstance(time, datetime.datetime):
- raise TypeError('Expecting datetime object.')
+ raise TypeError("Expecting datetime object.")
if self._not_valid_before is not None:
- raise ValueError('The not valid before may only be set once.')
+ raise ValueError("The not valid before may only be set once.")
time = _convert_to_naive_utc_time(time)
if time < _EARLIEST_UTC_TIME:
- raise ValueError('The not valid before date must be on or after'
- ' 1950 January 1).')
+ raise ValueError(
+ "The not valid before date must be on or after"
+ " 1950 January 1)."
+ )
if self._not_valid_after is not None and time > self._not_valid_after:
raise ValueError(
- 'The not valid before date must be before the not valid after '
- 'date.'
+ "The not valid before date must be before the not valid after "
+ "date."
)
return CertificateBuilder(
- self._issuer_name, self._subject_name,
- self._public_key, self._serial_number, time,
- self._not_valid_after, self._extensions
+ self._issuer_name,
+ self._subject_name,
+ self._public_key,
+ self._serial_number,
+ time,
+ self._not_valid_after,
+ self._extensions,
)
def not_valid_after(self, time):
@@ -535,23 +633,31 @@ class CertificateBuilder(object):
Sets the certificate expiration time.
"""
if not isinstance(time, datetime.datetime):
- raise TypeError('Expecting datetime object.')
+ raise TypeError("Expecting datetime object.")
if self._not_valid_after is not None:
- raise ValueError('The not valid after may only be set once.')
+ raise ValueError("The not valid after may only be set once.")
time = _convert_to_naive_utc_time(time)
if time < _EARLIEST_UTC_TIME:
- raise ValueError('The not valid after date must be on or after'
- ' 1950 January 1.')
- if (self._not_valid_before is not None and
- time < self._not_valid_before):
raise ValueError(
- 'The not valid after date must be after the not valid before '
- 'date.'
+ "The not valid after date must be on or after"
+ " 1950 January 1."
+ )
+ if (
+ self._not_valid_before is not None
+ and time < self._not_valid_before
+ ):
+ raise ValueError(
+ "The not valid after date must be after the not valid before "
+ "date."
)
return CertificateBuilder(
- self._issuer_name, self._subject_name,
- self._public_key, self._serial_number, self._not_valid_before,
- time, self._extensions
+ self._issuer_name,
+ self._subject_name,
+ self._public_key,
+ self._serial_number,
+ self._not_valid_before,
+ time,
+ self._extensions,
)
def add_extension(self, extension, critical):
@@ -565,15 +671,20 @@ class CertificateBuilder(object):
_reject_duplicate_extension(extension, self._extensions)
return CertificateBuilder(
- self._issuer_name, self._subject_name,
- self._public_key, self._serial_number, self._not_valid_before,
- self._not_valid_after, self._extensions + [extension]
+ self._issuer_name,
+ self._subject_name,
+ self._public_key,
+ self._serial_number,
+ self._not_valid_before,
+ self._not_valid_after,
+ self._extensions + [extension],
)
- def sign(self, private_key, algorithm, backend):
+ def sign(self, private_key, algorithm, backend=None):
"""
Signs the certificate using the CA's private key.
"""
+ backend = _get_backend(backend)
if self._subject_name is None:
raise ValueError("A certificate must have a subject name")
@@ -596,8 +707,14 @@ class CertificateBuilder(object):
class CertificateRevocationListBuilder(object):
- def __init__(self, issuer_name=None, last_update=None, next_update=None,
- extensions=[], revoked_certificates=[]):
+ def __init__(
+ self,
+ issuer_name=None,
+ last_update=None,
+ next_update=None,
+ extensions=[],
+ revoked_certificates=[],
+ ):
self._issuer_name = issuer_name
self._last_update = last_update
self._next_update = next_update
@@ -606,48 +723,59 @@ class CertificateRevocationListBuilder(object):
def issuer_name(self, issuer_name):
if not isinstance(issuer_name, Name):
- raise TypeError('Expecting x509.Name object.')
+ raise TypeError("Expecting x509.Name object.")
if self._issuer_name is not None:
- raise ValueError('The issuer name may only be set once.')
+ raise ValueError("The issuer name may only be set once.")
return CertificateRevocationListBuilder(
- issuer_name, self._last_update, self._next_update,
- self._extensions, self._revoked_certificates
+ issuer_name,
+ self._last_update,
+ self._next_update,
+ self._extensions,
+ self._revoked_certificates,
)
def last_update(self, last_update):
if not isinstance(last_update, datetime.datetime):
- raise TypeError('Expecting datetime object.')
+ raise TypeError("Expecting datetime object.")
if self._last_update is not None:
- raise ValueError('Last update may only be set once.')
+ raise ValueError("Last update may only be set once.")
last_update = _convert_to_naive_utc_time(last_update)
if last_update < _EARLIEST_UTC_TIME:
- raise ValueError('The last update date must be on or after'
- ' 1950 January 1.')
+ raise ValueError(
+ "The last update date must be on or after" " 1950 January 1."
+ )
if self._next_update is not None and last_update > self._next_update:
raise ValueError(
- 'The last update date must be before the next update date.'
+ "The last update date must be before the next update date."
)
return CertificateRevocationListBuilder(
- self._issuer_name, last_update, self._next_update,
- self._extensions, self._revoked_certificates
+ self._issuer_name,
+ last_update,
+ self._next_update,
+ self._extensions,
+ self._revoked_certificates,
)
def next_update(self, next_update):
if not isinstance(next_update, datetime.datetime):
- raise TypeError('Expecting datetime object.')
+ raise TypeError("Expecting datetime object.")
if self._next_update is not None:
- raise ValueError('Last update may only be set once.')
+ raise ValueError("Last update may only be set once.")
next_update = _convert_to_naive_utc_time(next_update)
if next_update < _EARLIEST_UTC_TIME:
- raise ValueError('The last update date must be on or after'
- ' 1950 January 1.')
+ raise ValueError(
+ "The last update date must be on or after" " 1950 January 1."
+ )
if self._last_update is not None and next_update < self._last_update:
raise ValueError(
- 'The next update date must be after the last update date.'
+ "The next update date must be after the last update date."
)
return CertificateRevocationListBuilder(
- self._issuer_name, self._last_update, next_update,
- self._extensions, self._revoked_certificates
+ self._issuer_name,
+ self._last_update,
+ next_update,
+ self._extensions,
+ self._revoked_certificates,
)
def add_extension(self, extension, critical):
@@ -660,8 +788,11 @@ class CertificateRevocationListBuilder(object):
extension = Extension(extension.oid, critical, extension)
_reject_duplicate_extension(extension, self._extensions)
return CertificateRevocationListBuilder(
- self._issuer_name, self._last_update, self._next_update,
- self._extensions + [extension], self._revoked_certificates
+ self._issuer_name,
+ self._last_update,
+ self._next_update,
+ self._extensions + [extension],
+ self._revoked_certificates,
)
def add_revoked_certificate(self, revoked_certificate):
@@ -672,12 +803,15 @@ class CertificateRevocationListBuilder(object):
raise TypeError("Must be an instance of RevokedCertificate")
return CertificateRevocationListBuilder(
- self._issuer_name, self._last_update,
- self._next_update, self._extensions,
- self._revoked_certificates + [revoked_certificate]
+ self._issuer_name,
+ self._last_update,
+ self._next_update,
+ self._extensions,
+ self._revoked_certificates + [revoked_certificate],
)
- def sign(self, private_key, algorithm, backend):
+ def sign(self, private_key, algorithm, backend=None):
+ backend = _get_backend(backend)
if self._issuer_name is None:
raise ValueError("A CRL must have an issuer name")
@@ -691,38 +825,41 @@ class CertificateRevocationListBuilder(object):
class RevokedCertificateBuilder(object):
- def __init__(self, serial_number=None, revocation_date=None,
- extensions=[]):
+ def __init__(
+ self, serial_number=None, revocation_date=None, extensions=[]
+ ):
self._serial_number = serial_number
self._revocation_date = revocation_date
self._extensions = extensions
def serial_number(self, number):
if not isinstance(number, six.integer_types):
- raise TypeError('Serial number must be of integral type.')
+ raise TypeError("Serial number must be of integral type.")
if self._serial_number is not None:
- raise ValueError('The serial number may only be set once.')
+ raise ValueError("The serial number may only be set once.")
if number <= 0:
- raise ValueError('The serial number should be positive')
+ raise ValueError("The serial number should be positive")
# ASN.1 integers are always signed, so most significant bit must be
# zero.
if number.bit_length() >= 160: # As defined in RFC 5280
- raise ValueError('The serial number should not be more than 159 '
- 'bits.')
+ raise ValueError(
+ "The serial number should not be more than 159 " "bits."
+ )
return RevokedCertificateBuilder(
number, self._revocation_date, self._extensions
)
def revocation_date(self, time):
if not isinstance(time, datetime.datetime):
- raise TypeError('Expecting datetime object.')
+ raise TypeError("Expecting datetime object.")
if self._revocation_date is not None:
- raise ValueError('The revocation date may only be set once.')
+ raise ValueError("The revocation date may only be set once.")
time = _convert_to_naive_utc_time(time)
if time < _EARLIEST_UTC_TIME:
- raise ValueError('The revocation date must be on or after'
- ' 1950 January 1.')
+ raise ValueError(
+ "The revocation date must be on or after" " 1950 January 1."
+ )
return RevokedCertificateBuilder(
self._serial_number, time, self._extensions
)
@@ -734,11 +871,13 @@ class RevokedCertificateBuilder(object):
extension = Extension(extension.oid, critical, extension)
_reject_duplicate_extension(extension, self._extensions)
return RevokedCertificateBuilder(
- self._serial_number, self._revocation_date,
- self._extensions + [extension]
+ self._serial_number,
+ self._revocation_date,
+ self._extensions + [extension],
)
- def build(self, backend):
+ def build(self, backend=None):
+ backend = _get_backend(backend)
if self._serial_number is None:
raise ValueError("A revoked certificate must have a serial number")
if self._revocation_date is None:
diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py
index 88afa3100..130ba69b8 100644
--- a/src/cryptography/x509/extensions.py
+++ b/src/cryptography/x509/extensions.py
@@ -10,21 +10,28 @@ import hashlib
import ipaddress
from enum import Enum
-from asn1crypto.keys import PublicKeyInfo
-
import six
from cryptography import utils
+from cryptography.hazmat._der import (
+ BIT_STRING,
+ DERReader,
+ OBJECT_IDENTIFIER,
+ SEQUENCE,
+)
from cryptography.hazmat.primitives import constant_time, serialization
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
from cryptography.x509.certificate_transparency import (
- SignedCertificateTimestamp
+ SignedCertificateTimestamp,
)
from cryptography.x509.general_name import GeneralName, IPAddress, OtherName
from cryptography.x509.name import RelativeDistinguishedName
from cryptography.x509.oid import (
- CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID, ObjectIdentifier,
+ CRLEntryExtensionOID,
+ ExtensionOID,
+ OCSPExtensionOID,
+ ObjectIdentifier,
)
@@ -37,20 +44,50 @@ def _key_identifier_from_public_key(public_key):
elif isinstance(public_key, EllipticCurvePublicKey):
data = public_key.public_bytes(
serialization.Encoding.X962,
- serialization.PublicFormat.UncompressedPoint
+ serialization.PublicFormat.UncompressedPoint,
)
else:
# This is a very slow way to do this.
serialized = public_key.public_bytes(
serialization.Encoding.DER,
- serialization.PublicFormat.SubjectPublicKeyInfo
+ serialization.PublicFormat.SubjectPublicKeyInfo,
)
- data = bytes(PublicKeyInfo.load(serialized)['public_key'])
+ reader = DERReader(serialized)
+ with reader.read_single_element(SEQUENCE) as public_key_info:
+ algorithm = public_key_info.read_element(SEQUENCE)
+ public_key = public_key_info.read_element(BIT_STRING)
+
+ # Double-check the algorithm structure.
+ with algorithm:
+ algorithm.read_element(OBJECT_IDENTIFIER)
+ if not algorithm.is_empty():
+ # Skip the optional parameters field.
+ algorithm.read_any_element()
+
+ # BIT STRING contents begin with the number of padding bytes added. It
+ # must be zero for SubjectPublicKeyInfo structures.
+ if public_key.read_byte() != 0:
+ raise ValueError("Invalid public key encoding")
+
+ data = public_key.data
return hashlib.sha1(data).digest()
+def _make_sequence_methods(field_name):
+ def len_method(self):
+ return len(getattr(self, field_name))
+
+ def iter_method(self):
+ return iter(getattr(self, field_name))
+
+ def getitem_method(self, idx):
+ return getattr(self, field_name)[idx]
+
+ return len_method, iter_method, getitem_method
+
+
class DuplicateExtension(Exception):
def __init__(self, msg, oid):
super(DuplicateExtension, self).__init__(msg)
@@ -81,7 +118,7 @@ class Extensions(object):
if ext.oid == oid:
return ext
- raise ExtensionNotFound("No {0} extension was found".format(oid), oid)
+ raise ExtensionNotFound("No {} extension was found".format(oid), oid)
def get_extension_for_class(self, extclass):
if extclass is UnrecognizedExtension:
@@ -96,22 +133,13 @@ class Extensions(object):
return ext
raise ExtensionNotFound(
- "No {0} extension was found".format(extclass), extclass.oid
+ "No {} extension was found".format(extclass), extclass.oid
)
- def __iter__(self):
- return iter(self._extensions)
-
- def __len__(self):
- return len(self._extensions)
-
- def __getitem__(self, idx):
- return self._extensions[idx]
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions")
def __repr__(self):
- return (
- "<Extensions({0})>".format(self._extensions)
- )
+ return "<Extensions({})>".format(self._extensions)
@utils.register_interface(ExtensionType)
@@ -137,7 +165,7 @@ class CRLNumber(object):
return hash(self.crl_number)
def __repr__(self):
- return "<CRLNumber({0})>".format(self.crl_number)
+ return "<CRLNumber({})>".format(self.crl_number)
crl_number = utils.read_only_property("_crl_number")
@@ -146,8 +174,12 @@ class CRLNumber(object):
class AuthorityKeyIdentifier(object):
oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER
- def __init__(self, key_identifier, authority_cert_issuer,
- authority_cert_serial_number):
+ def __init__(
+ self,
+ key_identifier,
+ authority_cert_issuer,
+ authority_cert_serial_number,
+ ):
if (authority_cert_issuer is None) != (
authority_cert_serial_number is None
):
@@ -169,9 +201,7 @@ class AuthorityKeyIdentifier(object):
if authority_cert_serial_number is not None and not isinstance(
authority_cert_serial_number, six.integer_types
):
- raise TypeError(
- "authority_cert_serial_number must be an integer"
- )
+ raise TypeError("authority_cert_serial_number must be an integer")
self._key_identifier = key_identifier
self._authority_cert_issuer = authority_cert_issuer
@@ -183,15 +213,15 @@ class AuthorityKeyIdentifier(object):
return cls(
key_identifier=digest,
authority_cert_issuer=None,
- authority_cert_serial_number=None
+ authority_cert_serial_number=None,
)
@classmethod
def from_issuer_subject_key_identifier(cls, ski):
return cls(
- key_identifier=ski.value.digest,
+ key_identifier=ski.digest,
authority_cert_issuer=None,
- authority_cert_serial_number=None
+ authority_cert_serial_number=None,
)
def __repr__(self):
@@ -207,10 +237,10 @@ class AuthorityKeyIdentifier(object):
return NotImplemented
return (
- self.key_identifier == other.key_identifier and
- self.authority_cert_issuer == other.authority_cert_issuer and
- self.authority_cert_serial_number ==
- other.authority_cert_serial_number
+ self.key_identifier == other.key_identifier
+ and self.authority_cert_issuer == other.authority_cert_issuer
+ and self.authority_cert_serial_number
+ == other.authority_cert_serial_number
)
def __ne__(self, other):
@@ -221,9 +251,9 @@ class AuthorityKeyIdentifier(object):
aci = None
else:
aci = tuple(self.authority_cert_issuer)
- return hash((
- self.key_identifier, aci, self.authority_cert_serial_number
- ))
+ return hash(
+ (self.key_identifier, aci, self.authority_cert_serial_number)
+ )
key_identifier = utils.read_only_property("_key_identifier")
authority_cert_issuer = utils.read_only_property("_authority_cert_issuer")
@@ -275,14 +305,10 @@ class AuthorityInformationAccess(object):
self._descriptions = descriptions
- def __iter__(self):
- return iter(self._descriptions)
-
- def __len__(self):
- return len(self._descriptions)
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
def __repr__(self):
- return "<AuthorityInformationAccess({0})>".format(self._descriptions)
+ return "<AuthorityInformationAccess({})>".format(self._descriptions)
def __eq__(self, other):
if not isinstance(other, AuthorityInformationAccess):
@@ -293,8 +319,37 @@ class AuthorityInformationAccess(object):
def __ne__(self, other):
return not self == other
- def __getitem__(self, idx):
- return self._descriptions[idx]
+ def __hash__(self):
+ return hash(tuple(self._descriptions))
+
+
+@utils.register_interface(ExtensionType)
+class SubjectInformationAccess(object):
+ oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS
+
+ def __init__(self, descriptions):
+ descriptions = list(descriptions)
+ if not all(isinstance(x, AccessDescription) for x in descriptions):
+ raise TypeError(
+ "Every item in the descriptions list must be an "
+ "AccessDescription"
+ )
+
+ self._descriptions = descriptions
+
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
+
+ def __repr__(self):
+ return "<SubjectInformationAccess({})>".format(self._descriptions)
+
+ def __eq__(self, other):
+ if not isinstance(other, SubjectInformationAccess):
+ return NotImplemented
+
+ return self._descriptions == other._descriptions
+
+ def __ne__(self, other):
+ return not self == other
def __hash__(self):
return hash(tuple(self._descriptions))
@@ -322,8 +377,8 @@ class AccessDescription(object):
return NotImplemented
return (
- self.access_method == other.access_method and
- self.access_location == other.access_location
+ self.access_method == other.access_method
+ and self.access_location == other.access_location
)
def __ne__(self, other):
@@ -347,9 +402,8 @@ class BasicConstraints(object):
if path_length is not None and not ca:
raise ValueError("path_length must be None when ca is False")
- if (
- path_length is not None and
- (not isinstance(path_length, six.integer_types) or path_length < 0)
+ if path_length is not None and (
+ not isinstance(path_length, six.integer_types) or path_length < 0
):
raise TypeError(
"path_length must be a non-negative integer or None"
@@ -362,8 +416,9 @@ class BasicConstraints(object):
path_length = utils.read_only_property("_path_length")
def __repr__(self):
- return ("<BasicConstraints(ca={0.ca}, "
- "path_length={0.path_length})>").format(self)
+ return (
+ "<BasicConstraints(ca={0.ca}, " "path_length={0.path_length})>"
+ ).format(self)
def __eq__(self, other):
if not isinstance(other, BasicConstraints):
@@ -422,14 +477,12 @@ class CRLDistributionPoints(object):
self._distribution_points = distribution_points
- def __iter__(self):
- return iter(self._distribution_points)
-
- def __len__(self):
- return len(self._distribution_points)
+ __len__, __iter__, __getitem__ = _make_sequence_methods(
+ "_distribution_points"
+ )
def __repr__(self):
- return "<CRLDistributionPoints({0})>".format(self._distribution_points)
+ return "<CRLDistributionPoints({})>".format(self._distribution_points)
def __eq__(self, other):
if not isinstance(other, CRLDistributionPoints):
@@ -440,9 +493,6 @@ class CRLDistributionPoints(object):
def __ne__(self, other):
return not self == other
- def __getitem__(self, idx):
- return self._distribution_points[idx]
-
def __hash__(self):
return hash(tuple(self._distribution_points))
@@ -463,14 +513,12 @@ class FreshestCRL(object):
self._distribution_points = distribution_points
- def __iter__(self):
- return iter(self._distribution_points)
-
- def __len__(self):
- return len(self._distribution_points)
+ __len__, __iter__, __getitem__ = _make_sequence_methods(
+ "_distribution_points"
+ )
def __repr__(self):
- return "<FreshestCRL({0})>".format(self._distribution_points)
+ return "<FreshestCRL({})>".format(self._distribution_points)
def __eq__(self, other):
if not isinstance(other, FreshestCRL):
@@ -481,9 +529,6 @@ class FreshestCRL(object):
def __ne__(self, other):
return not self == other
- def __getitem__(self, idx):
- return self._distribution_points[idx]
-
def __hash__(self):
return hash(tuple(self._distribution_points))
@@ -516,14 +561,15 @@ class DistributionPoint(object):
"crl_issuer must be None or a list of general names"
)
- if reasons and (not isinstance(reasons, frozenset) or not all(
- isinstance(x, ReasonFlags) for x in reasons
- )):
+ if reasons and (
+ not isinstance(reasons, frozenset)
+ or not all(isinstance(x, ReasonFlags) for x in reasons)
+ ):
raise TypeError("reasons must be None or frozenset of ReasonFlags")
if reasons and (
- ReasonFlags.unspecified in reasons or
- ReasonFlags.remove_from_crl in reasons
+ ReasonFlags.unspecified in reasons
+ or ReasonFlags.remove_from_crl in reasons
):
raise ValueError(
"unspecified and remove_from_crl are not valid reasons in a "
@@ -544,8 +590,8 @@ class DistributionPoint(object):
def __repr__(self):
return (
"<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
- "tive_name}, reasons={0.reasons}, crl_issuer={0.crl_issuer})>"
- .format(self)
+ "tive_name}, reasons={0.reasons}, "
+ "crl_issuer={0.crl_issuer})>".format(self)
)
def __eq__(self, other):
@@ -553,10 +599,10 @@ class DistributionPoint(object):
return NotImplemented
return (
- self.full_name == other.full_name and
- self.relative_name == other.relative_name and
- self.reasons == other.reasons and
- self.crl_issuer == other.crl_issuer
+ self.full_name == other.full_name
+ and self.relative_name == other.relative_name
+ and self.reasons == other.reasons
+ and self.crl_issuer == other.crl_issuer
)
def __ne__(self, other):
@@ -635,8 +681,8 @@ class PolicyConstraints(object):
return NotImplemented
return (
- self.require_explicit_policy == other.require_explicit_policy and
- self.inhibit_policy_mapping == other.inhibit_policy_mapping
+ self.require_explicit_policy == other.require_explicit_policy
+ and self.inhibit_policy_mapping == other.inhibit_policy_mapping
)
def __ne__(self, other):
@@ -669,14 +715,10 @@ class CertificatePolicies(object):
self._policies = policies
- def __iter__(self):
- return iter(self._policies)
-
- def __len__(self):
- return len(self._policies)
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_policies")
def __repr__(self):
- return "<CertificatePolicies({0})>".format(self._policies)
+ return "<CertificatePolicies({})>".format(self._policies)
def __eq__(self, other):
if not isinstance(other, CertificatePolicies):
@@ -687,9 +729,6 @@ class CertificatePolicies(object):
def __ne__(self, other):
return not self == other
- def __getitem__(self, idx):
- return self._policies[idx]
-
def __hash__(self):
return hash(tuple(self._policies))
@@ -704,8 +743,8 @@ class PolicyInformation(object):
if policy_qualifiers:
policy_qualifiers = list(policy_qualifiers)
if not all(
- isinstance(x, (six.text_type, UserNotice))
- for x in policy_qualifiers
+ isinstance(x, (six.text_type, UserNotice))
+ for x in policy_qualifiers
):
raise TypeError(
"policy_qualifiers must be a list of strings and/or "
@@ -725,8 +764,8 @@ class PolicyInformation(object):
return NotImplemented
return (
- self.policy_identifier == other.policy_identifier and
- self.policy_qualifiers == other.policy_qualifiers
+ self.policy_identifier == other.policy_identifier
+ and self.policy_qualifiers == other.policy_qualifiers
)
def __ne__(self, other):
@@ -767,8 +806,8 @@ class UserNotice(object):
return NotImplemented
return (
- self.notice_reference == other.notice_reference and
- self.explicit_text == other.explicit_text
+ self.notice_reference == other.notice_reference
+ and self.explicit_text == other.explicit_text
)
def __ne__(self, other):
@@ -786,9 +825,7 @@ class NoticeReference(object):
self._organization = organization
notice_numbers = list(notice_numbers)
if not all(isinstance(x, int) for x in notice_numbers):
- raise TypeError(
- "notice_numbers must be a list of integers"
- )
+ raise TypeError("notice_numbers must be a list of integers")
self._notice_numbers = notice_numbers
@@ -803,8 +840,8 @@ class NoticeReference(object):
return NotImplemented
return (
- self.organization == other.organization and
- self.notice_numbers == other.notice_numbers
+ self.organization == other.organization
+ and self.notice_numbers == other.notice_numbers
)
def __ne__(self, other):
@@ -830,14 +867,10 @@ class ExtendedKeyUsage(object):
self._usages = usages
- def __iter__(self):
- return iter(self._usages)
-
- def __len__(self):
- return len(self._usages)
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_usages")
def __repr__(self):
- return "<ExtendedKeyUsage({0})>".format(self._usages)
+ return "<ExtendedKeyUsage({})>".format(self._usages)
def __eq__(self, other):
if not isinstance(other, ExtendedKeyUsage):
@@ -856,11 +889,41 @@ class ExtendedKeyUsage(object):
class OCSPNoCheck(object):
oid = ExtensionOID.OCSP_NO_CHECK
+ def __eq__(self, other):
+ if not isinstance(other, OCSPNoCheck):
+ return NotImplemented
+
+ return True
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __hash__(self):
+ return hash(OCSPNoCheck)
+
+ def __repr__(self):
+ return "<OCSPNoCheck()>"
+
@utils.register_interface(ExtensionType)
class PrecertPoison(object):
oid = ExtensionOID.PRECERT_POISON
+ def __eq__(self, other):
+ if not isinstance(other, PrecertPoison):
+ return NotImplemented
+
+ return True
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __hash__(self):
+ return hash(PrecertPoison)
+
+ def __repr__(self):
+ return "<PrecertPoison()>"
+
@utils.register_interface(ExtensionType)
class TLSFeature(object):
@@ -869,8 +932,8 @@ class TLSFeature(object):
def __init__(self, features):
features = list(features)
if (
- not all(isinstance(x, TLSFeatureType) for x in features) or
- len(features) == 0
+ not all(isinstance(x, TLSFeatureType) for x in features)
+ or len(features) == 0
):
raise TypeError(
"features must be a list of elements from the TLSFeatureType "
@@ -879,11 +942,7 @@ class TLSFeature(object):
self._features = features
- def __iter__(self):
- return iter(self._features)
-
- def __len__(self):
- return len(self._features)
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_features")
def __repr__(self):
return "<TLSFeature(features={0._features})>".format(self)
@@ -894,9 +953,6 @@ class TLSFeature(object):
return self._features == other._features
- def __getitem__(self, idx):
- return self._features[idx]
-
def __ne__(self, other):
return not self == other
@@ -915,7 +971,7 @@ class TLSFeatureType(Enum):
status_request_v2 = 17
-_TLS_FEATURE_TYPE_TO_ENUM = dict((x.value, x) for x in TLSFeatureType)
+_TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType}
@utils.register_interface(ExtensionType)
@@ -953,9 +1009,18 @@ class InhibitAnyPolicy(object):
class KeyUsage(object):
oid = ExtensionOID.KEY_USAGE
- def __init__(self, digital_signature, content_commitment, key_encipherment,
- data_encipherment, key_agreement, key_cert_sign, crl_sign,
- encipher_only, decipher_only):
+ def __init__(
+ self,
+ digital_signature,
+ content_commitment,
+ key_encipherment,
+ data_encipherment,
+ key_agreement,
+ key_cert_sign,
+ crl_sign,
+ encipher_only,
+ decipher_only,
+ ):
if not key_agreement and (encipher_only or decipher_only):
raise ValueError(
"encipher_only and decipher_only can only be true when "
@@ -1003,45 +1068,55 @@ class KeyUsage(object):
encipher_only = self.encipher_only
decipher_only = self.decipher_only
except ValueError:
- encipher_only = None
- decipher_only = None
-
- return ("<KeyUsage(digital_signature={0.digital_signature}, "
- "content_commitment={0.content_commitment}, "
- "key_encipherment={0.key_encipherment}, "
- "data_encipherment={0.data_encipherment}, "
- "key_agreement={0.key_agreement}, "
- "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
- "encipher_only={1}, decipher_only={2})>").format(
- self, encipher_only, decipher_only)
+ # Users found None confusing because even though encipher/decipher
+ # have no meaning unless key_agreement is true, to construct an
+ # instance of the class you still need to pass False.
+ encipher_only = False
+ decipher_only = False
+
+ return (
+ "<KeyUsage(digital_signature={0.digital_signature}, "
+ "content_commitment={0.content_commitment}, "
+ "key_encipherment={0.key_encipherment}, "
+ "data_encipherment={0.data_encipherment}, "
+ "key_agreement={0.key_agreement}, "
+ "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
+ "encipher_only={1}, decipher_only={2})>"
+ ).format(self, encipher_only, decipher_only)
def __eq__(self, other):
if not isinstance(other, KeyUsage):
return NotImplemented
return (
- self.digital_signature == other.digital_signature and
- self.content_commitment == other.content_commitment and
- self.key_encipherment == other.key_encipherment and
- self.data_encipherment == other.data_encipherment and
- self.key_agreement == other.key_agreement and
- self.key_cert_sign == other.key_cert_sign and
- self.crl_sign == other.crl_sign and
- self._encipher_only == other._encipher_only and
- self._decipher_only == other._decipher_only
+ self.digital_signature == other.digital_signature
+ and self.content_commitment == other.content_commitment
+ and self.key_encipherment == other.key_encipherment
+ and self.data_encipherment == other.data_encipherment
+ and self.key_agreement == other.key_agreement
+ and self.key_cert_sign == other.key_cert_sign
+ and self.crl_sign == other.crl_sign
+ and self._encipher_only == other._encipher_only
+ and self._decipher_only == other._decipher_only
)
def __ne__(self, other):
return not self == other
def __hash__(self):
- return hash((
- self.digital_signature, self.content_commitment,
- self.key_encipherment, self.data_encipherment,
- self.key_agreement, self.key_cert_sign,
- self.crl_sign, self._encipher_only,
- self._decipher_only
- ))
+ return hash(
+ (
+ self.digital_signature,
+ self.content_commitment,
+ self.key_encipherment,
+ self.data_encipherment,
+ self.key_agreement,
+ self.key_cert_sign,
+ self.crl_sign,
+ self._encipher_only,
+ self._decipher_only,
+ )
+ )
@utils.register_interface(ExtensionType)
@@ -1051,9 +1126,7 @@ class NameConstraints(object):
def __init__(self, permitted_subtrees, excluded_subtrees):
if permitted_subtrees is not None:
permitted_subtrees = list(permitted_subtrees)
- if not all(
- isinstance(x, GeneralName) for x in permitted_subtrees
- ):
+ if not all(isinstance(x, GeneralName) for x in permitted_subtrees):
raise TypeError(
"permitted_subtrees must be a list of GeneralName objects "
"or None"
@@ -1063,9 +1136,7 @@ class NameConstraints(object):
if excluded_subtrees is not None:
excluded_subtrees = list(excluded_subtrees)
- if not all(
- isinstance(x, GeneralName) for x in excluded_subtrees
- ):
+ if not all(isinstance(x, GeneralName) for x in excluded_subtrees):
raise TypeError(
"excluded_subtrees must be a list of GeneralName objects "
"or None"
@@ -1087,17 +1158,21 @@ class NameConstraints(object):
return NotImplemented
return (
- self.excluded_subtrees == other.excluded_subtrees and
- self.permitted_subtrees == other.permitted_subtrees
+ self.excluded_subtrees == other.excluded_subtrees
+ and self.permitted_subtrees == other.permitted_subtrees
)
def __ne__(self, other):
return not self == other
def _validate_ip_name(self, tree):
- if any(isinstance(name, IPAddress) and not isinstance(
- name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
- ) for name in tree):
+ if any(
+ isinstance(name, IPAddress)
+ and not isinstance(
+ name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
+ )
+ for name in tree
+ ):
raise TypeError(
"IPAddress name constraints must be an IPv4Network or"
" IPv6Network object"
@@ -1145,17 +1220,19 @@ class Extension(object):
value = utils.read_only_property("_value")
def __repr__(self):
- return ("<Extension(oid={0.oid}, critical={0.critical}, "
- "value={0.value})>").format(self)
+ return (
+ "<Extension(oid={0.oid}, critical={0.critical}, "
+ "value={0.value})>"
+ ).format(self)
def __eq__(self, other):
if not isinstance(other, Extension):
return NotImplemented
return (
- self.oid == other.oid and
- self.critical == other.critical and
- self.value == other.value
+ self.oid == other.oid
+ and self.critical == other.critical
+ and self.value == other.value
)
def __ne__(self, other):
@@ -1176,11 +1253,7 @@ class GeneralNames(object):
self._general_names = general_names
- def __iter__(self):
- return iter(self._general_names)
-
- def __len__(self):
- return len(self._general_names)
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
def get_values_for_type(self, type):
# Return the value of each GeneralName, except for OtherName instances
@@ -1192,7 +1265,7 @@ class GeneralNames(object):
return list(objs)
def __repr__(self):
- return "<GeneralNames({0})>".format(self._general_names)
+ return "<GeneralNames({})>".format(self._general_names)
def __eq__(self, other):
if not isinstance(other, GeneralNames):
@@ -1203,9 +1276,6 @@ class GeneralNames(object):
def __ne__(self, other):
return not self == other
- def __getitem__(self, idx):
- return self._general_names[idx]
-
def __hash__(self):
return hash(tuple(self._general_names))
@@ -1217,17 +1287,13 @@ class SubjectAlternativeName(object):
def __init__(self, general_names):
self._general_names = GeneralNames(general_names)
- def __iter__(self):
- return iter(self._general_names)
-
- def __len__(self):
- return len(self._general_names)
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
def get_values_for_type(self, type):
return self._general_names.get_values_for_type(type)
def __repr__(self):
- return "<SubjectAlternativeName({0})>".format(self._general_names)
+ return "<SubjectAlternativeName({})>".format(self._general_names)
def __eq__(self, other):
if not isinstance(other, SubjectAlternativeName):
@@ -1235,9 +1301,6 @@ class SubjectAlternativeName(object):
return self._general_names == other._general_names
- def __getitem__(self, idx):
- return self._general_names[idx]
-
def __ne__(self, other):
return not self == other
@@ -1252,17 +1315,13 @@ class IssuerAlternativeName(object):
def __init__(self, general_names):
self._general_names = GeneralNames(general_names)
- def __iter__(self):
- return iter(self._general_names)
-
- def __len__(self):
- return len(self._general_names)
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
def get_values_for_type(self, type):
return self._general_names.get_values_for_type(type)
def __repr__(self):
- return "<IssuerAlternativeName({0})>".format(self._general_names)
+ return "<IssuerAlternativeName({})>".format(self._general_names)
def __eq__(self, other):
if not isinstance(other, IssuerAlternativeName):
@@ -1273,9 +1332,6 @@ class IssuerAlternativeName(object):
def __ne__(self, other):
return not self == other
- def __getitem__(self, idx):
- return self._general_names[idx]
-
def __hash__(self):
return hash(self._general_names)
@@ -1287,17 +1343,13 @@ class CertificateIssuer(object):
def __init__(self, general_names):
self._general_names = GeneralNames(general_names)
- def __iter__(self):
- return iter(self._general_names)
-
- def __len__(self):
- return len(self._general_names)
+ __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
def get_values_for_type(self, type):
return self._general_names.get_values_for_type(type)
def __repr__(self):
- return "<CertificateIssuer({0})>".format(self._general_names)
+ return "<CertificateIssuer({})>".format(self._general_names)
def __eq__(self, other):
if not isinstance(other, CertificateIssuer):
@@ -1308,9 +1360,6 @@ class CertificateIssuer(object):
def __ne__(self, other):
return not self == other
- def __getitem__(self, idx):
- return self._general_names[idx]
-
def __hash__(self):
return hash(self._general_names)
@@ -1326,7 +1375,7 @@ class CRLReason(object):
self._reason = reason
def __repr__(self):
- return "<CRLReason(reason={0})>".format(self._reason)
+ return "<CRLReason(reason={})>".format(self._reason)
def __eq__(self, other):
if not isinstance(other, CRLReason):
@@ -1354,7 +1403,7 @@ class InvalidityDate(object):
self._invalidity_date = invalidity_date
def __repr__(self):
- return "<InvalidityDate(invalidity_date={0})>".format(
+ return "<InvalidityDate(invalidity_date={})>".format(
self._invalidity_date
)
@@ -1389,32 +1438,64 @@ class PrecertificateSignedCertificateTimestamps(object):
)
self._signed_certificate_timestamps = signed_certificate_timestamps
- def __iter__(self):
- return iter(self._signed_certificate_timestamps)
+ __len__, __iter__, __getitem__ = _make_sequence_methods(
+ "_signed_certificate_timestamps"
+ )
- def __len__(self):
- return len(self._signed_certificate_timestamps)
+ def __repr__(self):
+ return "<PrecertificateSignedCertificateTimestamps({})>".format(
+ list(self)
+ )
- def __getitem__(self, idx):
- return self._signed_certificate_timestamps[idx]
+ def __hash__(self):
+ return hash(tuple(self._signed_certificate_timestamps))
+
+ def __eq__(self, other):
+ if not isinstance(other, PrecertificateSignedCertificateTimestamps):
+ return NotImplemented
- def __repr__(self):
return (
- "<PrecertificateSignedCertificateTimestamps({0})>".format(
- list(self)
- )
+ self._signed_certificate_timestamps
+ == other._signed_certificate_timestamps
)
+ def __ne__(self, other):
+ return not self == other
+
+
+@utils.register_interface(ExtensionType)
+class SignedCertificateTimestamps(object):
+ oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS
+
+ def __init__(self, signed_certificate_timestamps):
+ signed_certificate_timestamps = list(signed_certificate_timestamps)
+ if not all(
+ isinstance(sct, SignedCertificateTimestamp)
+ for sct in signed_certificate_timestamps
+ ):
+ raise TypeError(
+ "Every item in the signed_certificate_timestamps list must be "
+ "a SignedCertificateTimestamp"
+ )
+ self._signed_certificate_timestamps = signed_certificate_timestamps
+
+ __len__, __iter__, __getitem__ = _make_sequence_methods(
+ "_signed_certificate_timestamps"
+ )
+
+ def __repr__(self):
+ return "<SignedCertificateTimestamps({})>".format(list(self))
+
def __hash__(self):
return hash(tuple(self._signed_certificate_timestamps))
def __eq__(self, other):
- if not isinstance(other, PrecertificateSignedCertificateTimestamps):
+ if not isinstance(other, SignedCertificateTimestamps):
return NotImplemented
return (
- self._signed_certificate_timestamps ==
- other._signed_certificate_timestamps
+ self._signed_certificate_timestamps
+ == other._signed_certificate_timestamps
)
def __ne__(self, other):
@@ -1453,23 +1534,27 @@ class OCSPNonce(object):
class IssuingDistributionPoint(object):
oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT
- def __init__(self, full_name, relative_name, only_contains_user_certs,
- only_contains_ca_certs, only_some_reasons, indirect_crl,
- only_contains_attribute_certs):
- if (
- only_some_reasons and (
- not isinstance(only_some_reasons, frozenset) or not all(
- isinstance(x, ReasonFlags) for x in only_some_reasons
- )
- )
+ def __init__(
+ self,
+ full_name,
+ relative_name,
+ only_contains_user_certs,
+ only_contains_ca_certs,
+ only_some_reasons,
+ indirect_crl,
+ only_contains_attribute_certs,
+ ):
+ if only_some_reasons and (
+ not isinstance(only_some_reasons, frozenset)
+ or not all(isinstance(x, ReasonFlags) for x in only_some_reasons)
):
raise TypeError(
"only_some_reasons must be None or frozenset of ReasonFlags"
)
if only_some_reasons and (
- ReasonFlags.unspecified in only_some_reasons or
- ReasonFlags.remove_from_crl in only_some_reasons
+ ReasonFlags.unspecified in only_some_reasons
+ or ReasonFlags.remove_from_crl in only_some_reasons
):
raise ValueError(
"unspecified and remove_from_crl are not valid reasons in an "
@@ -1477,10 +1562,10 @@ class IssuingDistributionPoint(object):
)
if not (
- isinstance(only_contains_user_certs, bool) and
- isinstance(only_contains_ca_certs, bool) and
- isinstance(indirect_crl, bool) and
- isinstance(only_contains_attribute_certs, bool)
+ isinstance(only_contains_user_certs, bool)
+ and isinstance(only_contains_ca_certs, bool)
+ and isinstance(indirect_crl, bool)
+ and isinstance(only_contains_attribute_certs, bool)
):
raise TypeError(
"only_contains_user_certs, only_contains_ca_certs, "
@@ -1489,8 +1574,10 @@ class IssuingDistributionPoint(object):
)
crl_constraints = [
- only_contains_user_certs, only_contains_ca_certs,
- indirect_crl, only_contains_attribute_certs
+ only_contains_user_certs,
+ only_contains_ca_certs,
+ indirect_crl,
+ only_contains_attribute_certs,
]
if len([x for x in crl_constraints if x]) > 1:
@@ -1500,12 +1587,16 @@ class IssuingDistributionPoint(object):
"indirect_crl, only_contains_attribute_certs"
)
- if (
- not any([
- only_contains_user_certs, only_contains_ca_certs,
- indirect_crl, only_contains_attribute_certs, full_name,
- relative_name, only_some_reasons
- ])
+ if not any(
+ [
+ only_contains_user_certs,
+ only_contains_ca_certs,
+ indirect_crl,
+ only_contains_attribute_certs,
+ full_name,
+ relative_name,
+ only_some_reasons,
+ ]
):
raise ValueError(
"Cannot create empty extension: "
@@ -1540,29 +1631,31 @@ class IssuingDistributionPoint(object):
return NotImplemented
return (
- self.full_name == other.full_name and
- self.relative_name == other.relative_name and
- self.only_contains_user_certs == other.only_contains_user_certs and
- self.only_contains_ca_certs == other.only_contains_ca_certs and
- self.only_some_reasons == other.only_some_reasons and
- self.indirect_crl == other.indirect_crl and
- self.only_contains_attribute_certs ==
- other.only_contains_attribute_certs
+ self.full_name == other.full_name
+ and self.relative_name == other.relative_name
+ and self.only_contains_user_certs == other.only_contains_user_certs
+ and self.only_contains_ca_certs == other.only_contains_ca_certs
+ and self.only_some_reasons == other.only_some_reasons
+ and self.indirect_crl == other.indirect_crl
+ and self.only_contains_attribute_certs
+ == other.only_contains_attribute_certs
)
def __ne__(self, other):
return not self == other
def __hash__(self):
- return hash((
- self.full_name,
- self.relative_name,
- self.only_contains_user_certs,
- self.only_contains_ca_certs,
- self.only_some_reasons,
- self.indirect_crl,
- self.only_contains_attribute_certs,
- ))
+ return hash(
+ (
+ self.full_name,
+ self.relative_name,
+ self.only_contains_user_certs,
+ self.only_contains_ca_certs,
+ self.only_some_reasons,
+ self.indirect_crl,
+ self.only_contains_attribute_certs,
+ )
+ )
full_name = utils.read_only_property("_full_name")
relative_name = utils.read_only_property("_relative_name")
@@ -1592,9 +1685,8 @@ class UnrecognizedExtension(object):
def __repr__(self):
return (
- "<UnrecognizedExtension(oid={0.oid}, value={0.value!r})>".format(
- self
- )
+ "<UnrecognizedExtension(oid={0.oid}, "
+ "value={0.value!r})>".format(self)
)
def __eq__(self, other):
diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py
index 1b0f8c8f9..9be9d8c99 100644
--- a/src/cryptography/x509/general_name.py
+++ b/src/cryptography/x509/general_name.py
@@ -6,11 +6,9 @@ from __future__ import absolute_import, division, print_function
import abc
import ipaddress
-import warnings
from email.utils import parseaddr
import six
-from six.moves import urllib_parse
from cryptography import utils
from cryptography.x509.name import Name
@@ -30,20 +28,6 @@ _GENERAL_NAMES = {
}
-def _lazy_import_idna():
- # Import idna lazily becase it allocates a decent amount of memory, and
- # we're only using it in deprecated paths.
- try:
- import idna
- return idna
- except ImportError:
- raise ImportError(
- "idna is not installed, but a deprecated feature that requires it"
- " was used. See: https://cryptography.io/en/latest/faq/#importe"
- "rror-idna-is-not-installed"
- )
-
-
class UnsupportedGeneralNameType(Exception):
def __init__(self, msg, type):
super(UnsupportedGeneralNameType, self).__init__(msg)
@@ -66,14 +50,10 @@ class RFC822Name(object):
try:
value.encode("ascii")
except UnicodeEncodeError:
- value = self._idna_encode(value)
- warnings.warn(
+ raise ValueError(
"RFC822Name values should be passed as an A-label string. "
"This means unicode characters should be encoded via "
- "idna. Support for passing unicode strings (aka U-label) "
- "will be removed in a future version.",
- utils.DeprecatedIn21,
- stacklevel=2,
+ "a library like idna."
)
else:
raise TypeError("value must be string")
@@ -94,12 +74,6 @@ class RFC822Name(object):
instance._value = value
return instance
- def _idna_encode(self, value):
- idna = _lazy_import_idna()
- _, address = parseaddr(value)
- parts = address.split(u"@")
- return parts[0] + "@" + idna.encode(parts[1]).decode("ascii")
-
def __repr__(self):
return "<RFC822Name(value={0!r})>".format(self.value)
@@ -116,16 +90,6 @@ class RFC822Name(object):
return hash(self.value)
-def _idna_encode(value):
- idna = _lazy_import_idna()
- # Retain prefixes '*.' for common/alt names and '.' for name constraints
- for prefix in ['*.', '.']:
- if value.startswith(prefix):
- value = value[len(prefix):]
- return prefix + idna.encode(value).decode("ascii")
- return idna.encode(value).decode("ascii")
-
-
@utils.register_interface(GeneralName)
class DNSName(object):
def __init__(self, value):
@@ -133,14 +97,10 @@ class DNSName(object):
try:
value.encode("ascii")
except UnicodeEncodeError:
- value = _idna_encode(value)
- warnings.warn(
+ raise ValueError(
"DNSName values should be passed as an A-label string. "
"This means unicode characters should be encoded via "
- "idna. Support for passing unicode strings (aka U-label) "
- "will be removed in a future version.",
- utils.DeprecatedIn21,
- stacklevel=2,
+ "a library like idna."
)
else:
raise TypeError("value must be string")
@@ -178,14 +138,10 @@ class UniformResourceIdentifier(object):
try:
value.encode("ascii")
except UnicodeEncodeError:
- value = self._idna_encode(value)
- warnings.warn(
+ raise ValueError(
"URI values should be passed as an A-label string. "
"This means unicode characters should be encoded via "
- "idna. Support for passing unicode strings (aka U-label) "
- " will be removed in a future version.",
- utils.DeprecatedIn21,
- stacklevel=2,
+ "a library like idna."
)
else:
raise TypeError("value must be string")
@@ -200,29 +156,6 @@ class UniformResourceIdentifier(object):
instance._value = value
return instance
- def _idna_encode(self, value):
- idna = _lazy_import_idna()
- parsed = urllib_parse.urlparse(value)
- if parsed.port:
- netloc = (
- idna.encode(parsed.hostname) +
- ":{0}".format(parsed.port).encode("ascii")
- ).decode("ascii")
- else:
- netloc = idna.encode(parsed.hostname).decode("ascii")
-
- # Note that building a URL in this fashion means it should be
- # semantically indistinguishable from the original but is not
- # guaranteed to be exactly the same.
- return urllib_parse.urlunparse((
- parsed.scheme,
- netloc,
- parsed.path,
- parsed.params,
- parsed.query,
- parsed.fragment
- ))
-
def __repr__(self):
return "<UniformResourceIdentifier(value={0!r})>".format(self.value)
@@ -250,7 +183,7 @@ class DirectoryName(object):
value = utils.read_only_property("_value")
def __repr__(self):
- return "<DirectoryName(value={0})>".format(self.value)
+ return "<DirectoryName(value={})>".format(self.value)
def __eq__(self, other):
if not isinstance(other, DirectoryName):
@@ -276,7 +209,7 @@ class RegisteredID(object):
value = utils.read_only_property("_value")
def __repr__(self):
- return "<RegisteredID(value={0})>".format(self.value)
+ return "<RegisteredID(value={})>".format(self.value)
def __eq__(self, other):
if not isinstance(other, RegisteredID):
@@ -300,8 +233,8 @@ class IPAddress(object):
ipaddress.IPv4Address,
ipaddress.IPv6Address,
ipaddress.IPv4Network,
- ipaddress.IPv6Network
- )
+ ipaddress.IPv6Network,
+ ),
):
raise TypeError(
"value must be an instance of ipaddress.IPv4Address, "
@@ -314,7 +247,7 @@ class IPAddress(object):
value = utils.read_only_property("_value")
def __repr__(self):
- return "<IPAddress(value={0})>".format(self.value)
+ return "<IPAddress(value={})>".format(self.value)
def __eq__(self, other):
if not isinstance(other, IPAddress):
@@ -344,8 +277,9 @@ class OtherName(object):
value = utils.read_only_property("_value")
def __repr__(self):
- return "<OtherName(type_id={0}, value={1!r})>".format(
- self.type_id, self.value)
+ return "<OtherName(type_id={}, value={!r})>".format(
+ self.type_id, self.value
+ )
def __eq__(self, other):
if not isinstance(other, OtherName):
diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py
index 026b79c2c..0be876a0e 100644
--- a/src/cryptography/x509/name.py
+++ b/src/cryptography/x509/name.py
@@ -9,6 +9,7 @@ from enum import Enum
import six
from cryptography import utils
+from cryptography.hazmat.backends import _get_backend
from cryptography.x509.oid import NameOID, ObjectIdentifier
@@ -25,7 +26,7 @@ class _ASN1Type(Enum):
BMPString = 30
-_ASN1_TYPE_TO_ENUM = dict((i.value, i) for i in _ASN1Type)
+_ASN1_TYPE_TO_ENUM = {i.value: i for i in _ASN1Type}
_SENTINEL = object()
_NAMEOID_DEFAULT_TYPE = {
NameOID.COUNTRY_NAME: _ASN1Type.PrintableString,
@@ -39,35 +40,38 @@ _NAMEOID_DEFAULT_TYPE = {
#: Short attribute names from RFC 4514:
#: https://tools.ietf.org/html/rfc4514#page-7
_NAMEOID_TO_NAME = {
- NameOID.COMMON_NAME: 'CN',
- NameOID.LOCALITY_NAME: 'L',
- NameOID.STATE_OR_PROVINCE_NAME: 'ST',
- NameOID.ORGANIZATION_NAME: 'O',
- NameOID.ORGANIZATIONAL_UNIT_NAME: 'OU',
- NameOID.COUNTRY_NAME: 'C',
- NameOID.STREET_ADDRESS: 'STREET',
- NameOID.DOMAIN_COMPONENT: 'DC',
- NameOID.USER_ID: 'UID',
+ NameOID.COMMON_NAME: "CN",
+ NameOID.LOCALITY_NAME: "L",
+ NameOID.STATE_OR_PROVINCE_NAME: "ST",
+ NameOID.ORGANIZATION_NAME: "O",
+ NameOID.ORGANIZATIONAL_UNIT_NAME: "OU",
+ NameOID.COUNTRY_NAME: "C",
+ NameOID.STREET_ADDRESS: "STREET",
+ NameOID.DOMAIN_COMPONENT: "DC",
+ NameOID.USER_ID: "UID",
}
def _escape_dn_value(val):
"""Escape special characters in RFC4514 Distinguished Name value."""
+ if not val:
+ return ""
+
# See https://tools.ietf.org/html/rfc4514#section-2.4
- val = val.replace('\\', '\\\\')
+ val = val.replace("\\", "\\\\")
val = val.replace('"', '\\"')
- val = val.replace('+', '\\+')
- val = val.replace(',', '\\,')
- val = val.replace(';', '\\;')
- val = val.replace('<', '\\<')
- val = val.replace('>', '\\>')
- val = val.replace('\0', '\\00')
-
- if val[0] in ('#', ' '):
- val = '\\' + val
- if val[-1] == ' ':
- val = val[:-1] + '\\ '
+ val = val.replace("+", "\\+")
+ val = val.replace(",", "\\,")
+ val = val.replace(";", "\\;")
+ val = val.replace("<", "\\<")
+ val = val.replace(">", "\\>")
+ val = val.replace("\0", "\\00")
+
+ if val[0] in ("#", " "):
+ val = "\\" + val
+ if val[-1] == " ":
+ val = val[:-1] + "\\ "
return val
@@ -80,22 +84,17 @@ class NameAttribute(object):
)
if not isinstance(value, six.text_type):
- raise TypeError(
- "value argument must be a text type."
- )
+ raise TypeError("value argument must be a text type.")
if (
- oid == NameOID.COUNTRY_NAME or
- oid == NameOID.JURISDICTION_COUNTRY_NAME
+ oid == NameOID.COUNTRY_NAME
+ or oid == NameOID.JURISDICTION_COUNTRY_NAME
):
if len(value.encode("utf8")) != 2:
raise ValueError(
"Country name must be a 2 character country code"
)
- if len(value) == 0:
- raise ValueError("Value cannot be an empty string")
-
# The appropriate ASN1 string type varies by OID and is defined across
# multiple RFCs including 2459, 3280, and 5280. In general UTF8String
# is preferred (2459), but 3280 and 5280 specify several OIDs with
@@ -123,16 +122,13 @@ class NameAttribute(object):
dotted string.
"""
key = _NAMEOID_TO_NAME.get(self.oid, self.oid.dotted_string)
- return '%s=%s' % (key, _escape_dn_value(self.value))
+ return "%s=%s" % (key, _escape_dn_value(self.value))
def __eq__(self, other):
if not isinstance(other, NameAttribute):
return NotImplemented
- return (
- self.oid == other.oid and
- self.value == other.value
- )
+ return self.oid == other.oid and self.value == other.value
def __ne__(self, other):
return not self == other
@@ -169,7 +165,7 @@ class RelativeDistinguishedName(object):
Within each RDN, attributes are joined by '+', although that is rarely
used in certificates.
"""
- return '+'.join(attr.rfc4514_string() for attr in self._attributes)
+ return "+".join(attr.rfc4514_string() for attr in self._attributes)
def __eq__(self, other):
if not isinstance(other, RelativeDistinguishedName):
@@ -190,7 +186,7 @@ class RelativeDistinguishedName(object):
return len(self._attributes)
def __repr__(self):
- return "<RelativeDistinguishedName({0})>".format(self.rfc4514_string())
+ return "<RelativeDistinguishedName({})>".format(self.rfc4514_string())
class Name(object):
@@ -216,9 +212,12 @@ class Name(object):
An X.509 name is a two-level structure: a list of sets of attributes.
Each list element is separated by ',' and within each list element, set
elements are separated by '+'. The latter is almost never used in
- real world certificates.
+ real world certificates. According to RFC4514 section 2.1 the
+ RDNSequence must be reversed when converting to string representation.
"""
- return ','.join(attr.rfc4514_string() for attr in self._attributes)
+ return ",".join(
+ attr.rfc4514_string() for attr in reversed(self._attributes)
+ )
def get_attributes_for_oid(self, oid):
return [i for i in self if i.oid == oid]
@@ -227,7 +226,8 @@ class Name(object):
def rdns(self):
return self._attributes
- def public_bytes(self, backend):
+ def public_bytes(self, backend=None):
+ backend = _get_backend(backend)
return backend.x509_name_bytes(self)
def __eq__(self, other):
@@ -253,4 +253,9 @@ class Name(object):
return sum(len(rdn) for rdn in self._attributes)
def __repr__(self):
- return "<Name({0})>".format(self.rfc4514_string())
+ rdns = ",".join(attr.rfc4514_string() for attr in self._attributes)
+
+ if six.PY2:
+ return "<Name({})>".format(rdns.encode("utf8"))
+ else:
+ return "<Name({})>".format(rdns)
diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py
index aae9b6262..f8e27224e 100644
--- a/src/cryptography/x509/ocsp.py
+++ b/src/cryptography/x509/ocsp.py
@@ -13,7 +13,9 @@ import six
from cryptography import x509
from cryptography.hazmat.primitives import hashes
from cryptography.x509.base import (
- _EARLIEST_UTC_TIME, _convert_to_naive_utc_time, _reject_duplicate_extension
+ _EARLIEST_UTC_TIME,
+ _convert_to_naive_utc_time,
+ _reject_duplicate_extension,
)
@@ -40,10 +42,13 @@ class OCSPResponseStatus(Enum):
UNAUTHORIZED = 6
-_RESPONSE_STATUS_TO_ENUM = dict((x.value, x) for x in OCSPResponseStatus)
+_RESPONSE_STATUS_TO_ENUM = {x.value: x for x in OCSPResponseStatus}
_ALLOWED_HASHES = (
- hashes.SHA1, hashes.SHA224, hashes.SHA256,
- hashes.SHA384, hashes.SHA512
+ hashes.SHA1,
+ hashes.SHA224,
+ hashes.SHA256,
+ hashes.SHA384,
+ hashes.SHA512,
)
@@ -60,16 +65,18 @@ class OCSPCertStatus(Enum):
UNKNOWN = 2
-_CERT_STATUS_TO_ENUM = dict((x.value, x) for x in OCSPCertStatus)
+_CERT_STATUS_TO_ENUM = {x.value: x for x in OCSPCertStatus}
def load_der_ocsp_request(data):
from cryptography.hazmat.backends.openssl.backend import backend
+
return backend.load_der_ocsp_request(data)
def load_der_ocsp_response(data):
from cryptography.hazmat.backends.openssl.backend import backend
+
return backend.load_der_ocsp_response(data)
@@ -83,9 +90,8 @@ class OCSPRequestBuilder(object):
raise ValueError("Only one certificate can be added to a request")
_verify_algorithm(algorithm)
- if (
- not isinstance(cert, x509.Certificate) or
- not isinstance(issuer, x509.Certificate)
+ if not isinstance(cert, x509.Certificate) or not isinstance(
+ issuer, x509.Certificate
):
raise TypeError("cert and issuer must be a Certificate")
@@ -104,6 +110,7 @@ class OCSPRequestBuilder(object):
def build(self):
from cryptography.hazmat.backends.openssl.backend import backend
+
if self._request is None:
raise ValueError("You must add a certificate before building")
@@ -111,20 +118,27 @@ class OCSPRequestBuilder(object):
class _SingleResponse(object):
- def __init__(self, cert, issuer, algorithm, cert_status, this_update,
- next_update, revocation_time, revocation_reason):
- if (
- not isinstance(cert, x509.Certificate) or
- not isinstance(issuer, x509.Certificate)
+ def __init__(
+ self,
+ cert,
+ issuer,
+ algorithm,
+ cert_status,
+ this_update,
+ next_update,
+ revocation_time,
+ revocation_reason,
+ ):
+ if not isinstance(cert, x509.Certificate) or not isinstance(
+ issuer, x509.Certificate
):
raise TypeError("cert and issuer must be a Certificate")
_verify_algorithm(algorithm)
if not isinstance(this_update, datetime.datetime):
raise TypeError("this_update must be a datetime object")
- if (
- next_update is not None and
- not isinstance(next_update, datetime.datetime)
+ if next_update is not None and not isinstance(
+ next_update, datetime.datetime
):
raise TypeError("next_update must be a datetime object or None")
@@ -155,12 +169,13 @@ class _SingleResponse(object):
revocation_time = _convert_to_naive_utc_time(revocation_time)
if revocation_time < _EARLIEST_UTC_TIME:
- raise ValueError('The revocation_time must be on or after'
- ' 1950 January 1.')
+ raise ValueError(
+ "The revocation_time must be on or after"
+ " 1950 January 1."
+ )
- if (
- revocation_reason is not None and
- not isinstance(revocation_reason, x509.ReasonFlags)
+ if revocation_reason is not None and not isinstance(
+ revocation_reason, x509.ReasonFlags
):
raise TypeError(
"revocation_reason must be an item from the ReasonFlags "
@@ -173,25 +188,43 @@ class _SingleResponse(object):
class OCSPResponseBuilder(object):
- def __init__(self, response=None, responder_id=None, certs=None,
- extensions=[]):
+ def __init__(
+ self, response=None, responder_id=None, certs=None, extensions=[]
+ ):
self._response = response
self._responder_id = responder_id
self._certs = certs
self._extensions = extensions
- def add_response(self, cert, issuer, algorithm, cert_status, this_update,
- next_update, revocation_time, revocation_reason):
+ def add_response(
+ self,
+ cert,
+ issuer,
+ algorithm,
+ cert_status,
+ this_update,
+ next_update,
+ revocation_time,
+ revocation_reason,
+ ):
if self._response is not None:
raise ValueError("Only one response per OCSPResponse.")
singleresp = _SingleResponse(
- cert, issuer, algorithm, cert_status, this_update, next_update,
- revocation_time, revocation_reason
+ cert,
+ issuer,
+ algorithm,
+ cert_status,
+ this_update,
+ next_update,
+ revocation_time,
+ revocation_reason,
)
return OCSPResponseBuilder(
- singleresp, self._responder_id,
- self._certs, self._extensions,
+ singleresp,
+ self._responder_id,
+ self._certs,
+ self._extensions,
)
def responder_id(self, encoding, responder_cert):
@@ -205,8 +238,10 @@ class OCSPResponseBuilder(object):
)
return OCSPResponseBuilder(
- self._response, (responder_cert, encoding),
- self._certs, self._extensions,
+ self._response,
+ (responder_cert, encoding),
+ self._certs,
+ self._extensions,
)
def certificates(self, certs):
@@ -218,8 +253,10 @@ class OCSPResponseBuilder(object):
if not all(isinstance(x, x509.Certificate) for x in certs):
raise TypeError("certs must be a list of Certificates")
return OCSPResponseBuilder(
- self._response, self._responder_id,
- certs, self._extensions,
+ self._response,
+ self._responder_id,
+ certs,
+ self._extensions,
)
def add_extension(self, extension, critical):
@@ -230,20 +267,20 @@ class OCSPResponseBuilder(object):
_reject_duplicate_extension(extension, self._extensions)
return OCSPResponseBuilder(
- self._response, self._responder_id,
- self._certs, self._extensions + [extension],
+ self._response,
+ self._responder_id,
+ self._certs,
+ self._extensions + [extension],
)
def sign(self, private_key, algorithm):
from cryptography.hazmat.backends.openssl.backend import backend
+
if self._response is None:
raise ValueError("You must add a response before signing")
if self._responder_id is None:
raise ValueError("You must add a responder_id before signing")
- if not isinstance(algorithm, hashes.HashAlgorithm):
- raise TypeError("Algorithm must be a registered hash algorithm.")
-
return backend.create_ocsp_response(
OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm
)
@@ -251,6 +288,7 @@ class OCSPResponseBuilder(object):
@classmethod
def build_unsuccessful(cls, response_status):
from cryptography.hazmat.backends.openssl.backend import backend
+
if not isinstance(response_status, OCSPResponseStatus):
raise TypeError(
"response_status must be an item from OCSPResponseStatus"
@@ -286,6 +324,7 @@ class OCSPRequest(object):
"""
The serial number of the cert whose status is being checked
"""
+
@abc.abstractmethod
def public_bytes(self, encoding):
"""
@@ -420,3 +459,9 @@ class OCSPResponse(object):
"""
The list of response extensions. Not single response extensions.
"""
+
+ @abc.abstractproperty
+ def single_extensions(self):
+ """
+ The list of single response extensions. Not response extensions.
+ """
diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py
index ec19007fe..2bf606e50 100644
--- a/src/cryptography/x509/oid.py
+++ b/src/cryptography/x509/oid.py
@@ -31,12 +31,11 @@ class ExtensionOID(object):
TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24")
CRL_NUMBER = ObjectIdentifier("2.5.29.20")
DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27")
- PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = (
- ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2")
- )
- PRECERT_POISON = (
- ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3")
+ PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier(
+ "1.3.6.1.4.1.11129.2.4.2"
)
+ PRECERT_POISON = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3")
+ SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.5")
class OCSPExtensionOID(object):
@@ -76,6 +75,10 @@ class NameOID(object):
BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15")
POSTAL_ADDRESS = ObjectIdentifier("2.5.4.16")
POSTAL_CODE = ObjectIdentifier("2.5.4.17")
+ INN = ObjectIdentifier("1.2.643.3.131.1.1")
+ OGRN = ObjectIdentifier("1.2.643.100.1")
+ SNILS = ObjectIdentifier("1.2.643.100.3")
+ UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2")
class SignatureAlgorithmOID(object):
@@ -96,6 +99,11 @@ class SignatureAlgorithmOID(object):
DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3")
DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1")
DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2")
+ ED25519 = ObjectIdentifier("1.3.101.112")
+ ED448 = ObjectIdentifier("1.3.101.113")
+ GOSTR3411_94_WITH_3410_2001 = ObjectIdentifier("1.2.643.2.2.3")
+ GOSTR3410_2012_WITH_3411_2012_256 = ObjectIdentifier("1.2.643.7.1.1.3.2")
+ GOSTR3410_2012_WITH_3411_2012_512 = ObjectIdentifier("1.2.643.7.1.1.3.3")
_SIG_OIDS_TO_HASH = {
@@ -113,7 +121,12 @@ _SIG_OIDS_TO_HASH = {
SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(),
SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(),
SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(),
- SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256()
+ SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256(),
+ SignatureAlgorithmOID.ED25519: None,
+ SignatureAlgorithmOID.ED448: None,
+ SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: None,
+ SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: None,
+ SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: None,
}
@@ -132,12 +145,21 @@ class AuthorityInformationAccessOID(object):
OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1")
+class SubjectInformationAccessOID(object):
+ CA_REPOSITORY = ObjectIdentifier("1.3.6.1.5.5.7.48.5")
+
+
class CertificatePoliciesOID(object):
CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1")
CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2")
ANY_POLICY = ObjectIdentifier("2.5.29.32.0")
+class AttributeOID(object):
+ CHALLENGE_PASSWORD = ObjectIdentifier("1.2.840.113549.1.9.7")
+ UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2")
+
+
_OID_NAMES = {
NameOID.COMMON_NAME: "commonName",
NameOID.COUNTRY_NAME: "countryName",
@@ -165,7 +187,10 @@ _OID_NAMES = {
NameOID.BUSINESS_CATEGORY: "businessCategory",
NameOID.POSTAL_ADDRESS: "postalAddress",
NameOID.POSTAL_CODE: "postalCode",
-
+ NameOID.INN: "INN",
+ NameOID.OGRN: "OGRN",
+ NameOID.SNILS: "SNILS",
+ NameOID.UNSTRUCTURED_NAME: "unstructuredName",
SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption",
SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption",
SignatureAlgorithmOID.RSA_WITH_SHA224: "sha224WithRSAEncryption",
@@ -181,6 +206,17 @@ _OID_NAMES = {
SignatureAlgorithmOID.DSA_WITH_SHA1: "dsa-with-sha1",
SignatureAlgorithmOID.DSA_WITH_SHA224: "dsa-with-sha224",
SignatureAlgorithmOID.DSA_WITH_SHA256: "dsa-with-sha256",
+ SignatureAlgorithmOID.ED25519: "ed25519",
+ SignatureAlgorithmOID.ED448: "ed448",
+ SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: (
+ "GOST R 34.11-94 with GOST R 34.10-2001"
+ ),
+ SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: (
+ "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)"
+ ),
+ SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: (
+ "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)"
+ ),
ExtendedKeyUsageOID.SERVER_AUTH: "serverAuth",
ExtendedKeyUsageOID.CLIENT_AUTH: "clientAuth",
ExtendedKeyUsageOID.CODE_SIGNING: "codeSigning",
@@ -196,6 +232,10 @@ _OID_NAMES = {
ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: (
"signedCertificateTimestampList"
),
+ ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: (
+ "signedCertificateTimestampList"
+ ),
+ ExtensionOID.PRECERT_POISON: "ctPoison",
CRLEntryExtensionOID.CRL_REASON: "cRLReason",
CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate",
CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer",
@@ -208,9 +248,7 @@ _OID_NAMES = {
ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage",
ExtensionOID.FRESHEST_CRL: "freshestCRL",
ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy",
- ExtensionOID.ISSUING_DISTRIBUTION_POINT: (
- "issuingDistributionPoint"
- ),
+ ExtensionOID.ISSUING_DISTRIBUTION_POINT: ("issuingDistributionPoint"),
ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess",
ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess",
ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck",
@@ -219,7 +257,9 @@ _OID_NAMES = {
ExtensionOID.TLS_FEATURE: "TLSFeature",
AuthorityInformationAccessOID.OCSP: "OCSP",
AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers",
+ SubjectInformationAccessOID.CA_REPOSITORY: "caRepository",
CertificatePoliciesOID.CPS_QUALIFIER: "id-qt-cps",
CertificatePoliciesOID.CPS_USER_NOTICE: "id-qt-unotice",
OCSPExtensionOID.NONCE: "OCSPNonce",
+ AttributeOID.CHALLENGE_PASSWORD: "challengePassword",
}
diff --git a/tests/conftest.py b/tests/conftest.py
index d858b4f70..ece7a11e7 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -9,12 +9,18 @@ import pytest
from cryptography.hazmat.backends.openssl import backend as openssl_backend
from .utils import (
- check_backend_support, load_wycheproof_tests, skip_if_wycheproof_none
+ check_backend_support,
+ load_wycheproof_tests,
)
def pytest_report_header(config):
- return "OpenSSL: {0}".format(openssl_backend.openssl_version_text())
+ return "\n".join(
+ [
+ "OpenSSL: {}".format(openssl_backend.openssl_version_text()),
+ "FIPS Enabled: {}".format(openssl_backend._fips_enabled),
+ ]
+ )
def pytest_addoption(parser):
@@ -23,8 +29,7 @@ def pytest_addoption(parser):
def pytest_generate_tests(metafunc):
if "wycheproof" in metafunc.fixturenames:
- wycheproof = metafunc.config.getoption("--wycheproof-root")
- skip_if_wycheproof_none(wycheproof)
+ wycheproof = metafunc.config.getoption("--wycheproof-root", skip=True)
testcases = []
marker = metafunc.definition.get_closest_marker("wycheproof_tests")
@@ -33,6 +38,12 @@ def pytest_generate_tests(metafunc):
metafunc.parametrize("wycheproof", testcases)
+def pytest_runtest_setup(item):
+ if openssl_backend._fips_enabled:
+ for marker in item.iter_markers(name="skip_fips"):
+ pytest.skip(marker.kwargs["reason"])
+
+
@pytest.fixture()
def backend(request):
required_interfaces = [
@@ -43,7 +54,7 @@ def backend(request):
isinstance(openssl_backend, iface) for iface in required_interfaces
):
pytest.skip(
- "OpenSSL doesn't implement required interfaces: {0}".format(
+ "OpenSSL doesn't implement required interfaces: {}".format(
required_interfaces
)
)
diff --git a/tests/hazmat/backends/test_no_backend.py b/tests/hazmat/backends/test_no_backend.py
new file mode 100644
index 000000000..67866929e
--- /dev/null
+++ b/tests/hazmat/backends/test_no_backend.py
@@ -0,0 +1,16 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+from cryptography.hazmat.backends import _get_backend, default_backend
+
+
+def test_get_backend_no_backend():
+ assert _get_backend(None) is default_backend()
+
+
+def test_get_backend():
+ faux_backend = object()
+ assert _get_backend(faux_backend) is faux_backend
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 0aa72d890..eab868fad 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -10,16 +10,12 @@ import subprocess
import sys
import textwrap
-from pkg_resources import parse_version
-
import pytest
from cryptography import x509
from cryptography.exceptions import InternalError, _Reasons
from cryptography.hazmat.backends.interfaces import DHBackend, RSABackend
-from cryptography.hazmat.backends.openssl.backend import (
- Backend, backend
-)
+from cryptography.hazmat.backends.openssl.backend import Backend, backend
from cryptography.hazmat.backends.openssl.ec import _sn_to_elliptic_curve
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import dh, dsa, padding
@@ -29,16 +25,21 @@ from cryptography.hazmat.primitives.ciphers.modes import CBC
from ..primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512
from ...doubles import (
- DummyAsymmetricPadding, DummyCipherAlgorithm, DummyHashAlgorithm, DummyMode
+ DummyAsymmetricPadding,
+ DummyCipherAlgorithm,
+ DummyHashAlgorithm,
+ DummyMode,
)
from ...utils import (
- load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
from ...x509.test_x509 import _load_cert
def skip_if_libre_ssl(openssl_version):
- if u'LibreSSL' in openssl_version:
+ if u"LibreSSL" in openssl_version:
pytest.skip("LibreSSL hard-codes RAND_bytes to use arc4random.")
@@ -68,10 +69,9 @@ class TestOpenSSL(object):
if it starts with OpenSSL or LibreSSL as that appears
to be true for every OpenSSL-alike.
"""
- assert (
- backend.openssl_version_text().startswith("OpenSSL") or
- backend.openssl_version_text().startswith("LibreSSL")
- )
+ assert backend.openssl_version_text().startswith(
+ "OpenSSL"
+ ) or backend.openssl_version_text().startswith("LibreSSL")
def test_openssl_version_number(self):
assert backend.openssl_version_number() > 0
@@ -89,10 +89,12 @@ class TestOpenSSL(object):
b.register_cipher_adapter(
DummyCipherAlgorithm,
type(mode),
- lambda backend, cipher, mode: backend._ffi.NULL
+ lambda backend, cipher, mode: backend._ffi.NULL,
)
cipher = Cipher(
- DummyCipherAlgorithm(), mode, backend=b,
+ DummyCipherAlgorithm(),
+ mode,
+ backend=b,
)
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
cipher.encryptor()
@@ -104,8 +106,9 @@ class TestOpenSSL(object):
def test_consume_errors(self):
for i in range(10):
- backend._lib.ERR_put_error(backend._lib.ERR_LIB_EVP, 0, 0,
- b"test_openssl.py", -1)
+ backend._lib.ERR_put_error(
+ backend._lib.ERR_LIB_EVP, 0, 0, b"test_openssl.py", -1
+ )
assert backend._lib.ERR_peek_error() != 0
@@ -124,17 +127,11 @@ class TestOpenSSL(object):
cipher = backend._lib.EVP_get_cipherbyname(b"aes-256-cbc")
assert cipher != backend._ffi.NULL
- def test_error_strings_loaded(self):
- buf = backend._ffi.new("char[]", 256)
- backend._lib.ERR_error_string_n(101183626, buf, len(buf))
- assert b"data not multiple of block length" in backend._ffi.string(buf)
-
def test_unknown_error_in_cipher_finalize(self):
cipher = Cipher(AES(b"\0" * 16), CBC(b"\0" * 16), backend=backend)
enc = cipher.encryptor()
enc.update(b"\0")
- backend._lib.ERR_put_error(0, 0, 1,
- b"test_openssl.py", -1)
+ backend._lib.ERR_put_error(0, 0, 1, b"test_openssl.py", -1)
with pytest.raises(InternalError):
enc.finalize()
@@ -170,6 +167,11 @@ class TestOpenSSL(object):
assert backend._bn_to_int(bn) == 0
+@pytest.mark.skipif(
+ not backend._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE,
+ reason="Requires OpenSSL with ENGINE support and OpenSSL < 1.1.1d",
+)
+@pytest.mark.skip_fips(reason="osrandom engine disabled for FIPS")
class TestOpenSSLRandomEngine(object):
def setup(self):
# The default RAND engine is global and shared between
@@ -178,7 +180,7 @@ class TestOpenSSLRandomEngine(object):
# that engine in teardown.
current_default = backend._lib.ENGINE_get_default_RAND()
name = backend._lib.ENGINE_get_name(current_default)
- assert name == backend._binding._osrandom_engine_name
+ assert name == backend._lib.Cryptography_osrandom_engine_name
def teardown(self):
# we need to reset state to being default. backend is a shared global
@@ -186,10 +188,11 @@ class TestOpenSSLRandomEngine(object):
backend.activate_osrandom_engine()
current_default = backend._lib.ENGINE_get_default_RAND()
name = backend._lib.ENGINE_get_name(current_default)
- assert name == backend._binding._osrandom_engine_name
+ assert name == backend._lib.Cryptography_osrandom_engine_name
- @pytest.mark.skipif(sys.executable is None,
- reason="No Python interpreter available.")
+ @pytest.mark.skipif(
+ sys.executable is None, reason="No Python interpreter available."
+ )
def test_osrandom_engine_is_default(self, tmpdir):
engine_printer = textwrap.dedent(
"""
@@ -203,7 +206,7 @@ class TestOpenSSLRandomEngine(object):
assert res == 1
"""
)
- engine_name = tmpdir.join('engine_name')
+ engine_name = tmpdir.join("engine_name")
# If we're running tests via ``python setup.py test`` in a clean
# environment then all of our dependencies are going to be installed
@@ -214,7 +217,7 @@ class TestOpenSSLRandomEngine(object):
env = os.environ.copy()
env["PYTHONPATH"] = os.pathsep.join(sys.path)
- with engine_name.open('w') as out:
+ with engine_name.open("w") as out:
subprocess.check_call(
[sys.executable, "-c", engine_printer],
env=env,
@@ -223,10 +226,10 @@ class TestOpenSSLRandomEngine(object):
)
osrandom_engine_name = backend._ffi.string(
- backend._binding._osrandom_engine_name
+ backend._lib.Cryptography_osrandom_engine_name
)
- assert engine_name.read().encode('ascii') == osrandom_engine_name
+ assert engine_name.read().encode("ascii") == osrandom_engine_name
def test_osrandom_sanity_check(self):
# This test serves as a check against catastrophic failure.
@@ -242,7 +245,7 @@ class TestOpenSSLRandomEngine(object):
backend.activate_osrandom_engine()
e = backend._lib.ENGINE_get_default_RAND()
name = backend._lib.ENGINE_get_name(e)
- assert name == backend._binding._osrandom_engine_name
+ assert name == backend._lib.Cryptography_osrandom_engine_name
res = backend._lib.ENGINE_free(e)
assert res == 1
@@ -250,7 +253,7 @@ class TestOpenSSLRandomEngine(object):
e = backend._lib.ENGINE_get_default_RAND()
assert e != backend._ffi.NULL
name = backend._lib.ENGINE_get_name(e)
- assert name == backend._binding._osrandom_engine_name
+ assert name == backend._lib.Cryptography_osrandom_engine_name
res = backend._lib.ENGINE_free(e)
assert res == 1
backend.activate_builtin_random()
@@ -267,33 +270,55 @@ class TestOpenSSLRandomEngine(object):
def test_osrandom_engine_implementation(self):
name = backend.osrandom_engine_implementation()
- assert name in ['/dev/urandom', 'CryptGenRandom', 'getentropy',
- 'getrandom']
- if sys.platform.startswith('linux'):
- assert name in ['getrandom', '/dev/urandom']
- if sys.platform == 'darwin':
- # macOS 10.12+ supports getentropy
- if parse_version(os.uname()[2]) >= parse_version("16.0"):
- assert name == 'getentropy'
- else:
- assert name == '/dev/urandom'
- if sys.platform == 'win32':
- assert name == 'CryptGenRandom'
+ assert name in [
+ "/dev/urandom",
+ "CryptGenRandom",
+ "getentropy",
+ "getrandom",
+ ]
+ if sys.platform.startswith("linux"):
+ assert name in ["getrandom", "/dev/urandom"]
+ if sys.platform == "darwin":
+ assert name in ["getentropy", "/dev/urandom"]
+ if sys.platform == "win32":
+ assert name == "CryptGenRandom"
def test_activate_osrandom_already_default(self):
e = backend._lib.ENGINE_get_default_RAND()
name = backend._lib.ENGINE_get_name(e)
- assert name == backend._binding._osrandom_engine_name
+ assert name == backend._lib.Cryptography_osrandom_engine_name
res = backend._lib.ENGINE_free(e)
assert res == 1
backend.activate_osrandom_engine()
e = backend._lib.ENGINE_get_default_RAND()
name = backend._lib.ENGINE_get_name(e)
- assert name == backend._binding._osrandom_engine_name
+ assert name == backend._lib.Cryptography_osrandom_engine_name
res = backend._lib.ENGINE_free(e)
assert res == 1
+@pytest.mark.skipif(
+ backend._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE,
+ reason="Requires OpenSSL without ENGINE support or OpenSSL >=1.1.1d",
+)
+class TestOpenSSLNoEngine(object):
+ def test_no_engine_support(self):
+ assert (
+ backend._ffi.string(backend._lib.Cryptography_osrandom_engine_id)
+ == b"no-engine-support"
+ )
+ assert (
+ backend._ffi.string(backend._lib.Cryptography_osrandom_engine_name)
+ == b"osrandom_engine disabled"
+ )
+
+ def test_activate_builtin_random_does_nothing(self):
+ backend.activate_builtin_random()
+
+ def test_activate_osrandom_does_nothing(self):
+ backend.activate_osrandom_engine()
+
+
class TestOpenSSLRSA(object):
def test_generate_rsa_parameters_supported(self):
assert backend.generate_rsa_parameters_supported(1, 1024) is False
@@ -310,17 +335,24 @@ class TestOpenSSLRSA(object):
def test_cant_generate_insecure_tiny_key(self):
with pytest.raises(ValueError):
- backend.generate_rsa_private_key(public_exponent=65537,
- key_size=511)
+ backend.generate_rsa_private_key(
+ public_exponent=65537, key_size=511
+ )
with pytest.raises(ValueError):
- backend.generate_rsa_private_key(public_exponent=65537,
- key_size=256)
+ backend.generate_rsa_private_key(
+ public_exponent=65537, key_size=256
+ )
def test_rsa_padding_unsupported_pss_mgf1_hash(self):
- assert backend.rsa_padding_supported(
- padding.PSS(mgf=padding.MGF1(DummyHashAlgorithm()), salt_length=0)
- ) is False
+ assert (
+ backend.rsa_padding_supported(
+ padding.PSS(
+ mgf=padding.MGF1(DummyHashAlgorithm()), salt_length=0
+ )
+ )
+ is False
+ )
def test_rsa_padding_unsupported(self):
assert backend.rsa_padding_supported(DummyAsymmetricPadding()) is False
@@ -329,22 +361,28 @@ class TestOpenSSLRSA(object):
assert backend.rsa_padding_supported(padding.PKCS1v15()) is True
def test_rsa_padding_supported_pss(self):
- assert backend.rsa_padding_supported(
- padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
- ) is True
+ assert (
+ backend.rsa_padding_supported(
+ padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
+ )
+ is True
+ )
def test_rsa_padding_supported_oaep(self):
- assert backend.rsa_padding_supported(
- padding.OAEP(
- mgf=padding.MGF1(algorithm=hashes.SHA1()),
- algorithm=hashes.SHA1(),
- label=None
- ),
- ) is True
+ assert (
+ backend.rsa_padding_supported(
+ padding.OAEP(
+ mgf=padding.MGF1(algorithm=hashes.SHA1()),
+ algorithm=hashes.SHA1(),
+ label=None,
+ ),
+ )
+ is True
+ )
@pytest.mark.skipif(
backend._lib.Cryptography_HAS_RSA_OAEP_MD == 0,
- reason="Requires OpenSSL with rsa_oaep_md (1.0.2+)"
+ reason="Requires OpenSSL with rsa_oaep_md (1.0.2+)",
)
def test_rsa_padding_supported_oaep_sha2_combinations(self):
hashalgs = [
@@ -355,30 +393,37 @@ class TestOpenSSLRSA(object):
hashes.SHA512(),
]
for mgf1alg, oaepalg in itertools.product(hashalgs, hashalgs):
- assert backend.rsa_padding_supported(
- padding.OAEP(
- mgf=padding.MGF1(algorithm=mgf1alg),
- algorithm=oaepalg,
- label=None
- ),
- ) is True
+ assert (
+ backend.rsa_padding_supported(
+ padding.OAEP(
+ mgf=padding.MGF1(algorithm=mgf1alg),
+ algorithm=oaepalg,
+ label=None,
+ ),
+ )
+ is True
+ )
def test_rsa_padding_unsupported_mgf(self):
- assert backend.rsa_padding_supported(
- padding.OAEP(
- mgf=DummyMGF(),
- algorithm=hashes.SHA1(),
- label=None
- ),
- ) is False
+ assert (
+ backend.rsa_padding_supported(
+ padding.OAEP(
+ mgf=DummyMGF(), algorithm=hashes.SHA1(), label=None
+ ),
+ )
+ is False
+ )
- assert backend.rsa_padding_supported(
- padding.PSS(mgf=DummyMGF(), salt_length=0)
- ) is False
+ assert (
+ backend.rsa_padding_supported(
+ padding.PSS(mgf=DummyMGF(), salt_length=0)
+ )
+ is False
+ )
@pytest.mark.skipif(
backend._lib.Cryptography_HAS_RSA_OAEP_MD == 1,
- reason="Requires OpenSSL without rsa_oaep_md (< 1.0.2)"
+ reason="Requires OpenSSL without rsa_oaep_md (< 1.0.2)",
)
def test_unsupported_mgf1_hash_algorithm_decrypt(self):
private_key = RSA_KEY_512.private_key(backend)
@@ -388,13 +433,13 @@ class TestOpenSSLRSA(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA1(),
- label=None
- )
+ label=None,
+ ),
)
@pytest.mark.skipif(
backend._lib.Cryptography_HAS_RSA_OAEP_MD == 1,
- reason="Requires OpenSSL without rsa_oaep_md (< 1.0.2)"
+ reason="Requires OpenSSL without rsa_oaep_md (< 1.0.2)",
)
def test_unsupported_oaep_hash_algorithm_decrypt(self):
private_key = RSA_KEY_512.private_key(backend)
@@ -404,8 +449,8 @@ class TestOpenSSLRSA(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA256(),
- label=None
- )
+ label=None,
+ ),
)
def test_unsupported_mgf1_hash_algorithm_md5_decrypt(self):
@@ -416,8 +461,8 @@ class TestOpenSSLRSA(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.MD5()),
algorithm=hashes.MD5(),
- label=None
- )
+ label=None,
+ ),
)
@@ -437,6 +482,16 @@ class TestOpenSSLSignX509Certificate(object):
)
+class TestOpenSSLSignX509CSR(object):
+ def test_requires_csr_builder(self):
+ private_key = RSA_KEY_2048.private_key(backend)
+
+ with pytest.raises(TypeError):
+ backend.create_x509_csr(
+ object(), private_key, DummyHashAlgorithm()
+ )
+
+
class TestOpenSSLSignX509CertificateRevocationList(object):
def test_invalid_builder(self):
private_key = RSA_KEY_2048.private_key(backend)
@@ -492,14 +547,15 @@ class TestOpenSSLSerializationWithOpenSSL(object):
with pytest.raises(ValueError):
load_vectors_from_file(
os.path.join(
- "asymmetric", "Traditional_OpenSSL_Serialization",
- "key1.pem"
+ "asymmetric",
+ "Traditional_OpenSSL_Serialization",
+ "key1.pem",
),
lambda pemfile: (
backend.load_pem_private_key(
pemfile.read().encode(), password
)
- )
+ ),
)
@@ -518,7 +574,7 @@ class TestRSAPEMSerialization(object):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
- serialization.BestAvailableEncryption(password)
+ serialization.BestAvailableEncryption(password),
)
@@ -527,9 +583,9 @@ class TestGOSTCertificate(object):
cert = _load_cert(
os.path.join("x509", "e-trust.ru.der"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
- if backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I:
+ if backend._lib.CRYPTOGRAPHY_IS_LIBRESSL:
with pytest.raises(ValueError) as exc:
cert.subject
@@ -538,42 +594,49 @@ class TestGOSTCertificate(object):
# erroneously pass.
assert str(exc.value) == "Unsupported ASN1 string type. Type: 18"
else:
- assert cert.subject.get_attributes_for_oid(
- x509.ObjectIdentifier("1.2.643.3.131.1.1")
- )[0].value == "007710474375"
+ assert (
+ cert.subject.get_attributes_for_oid(
+ x509.ObjectIdentifier("1.2.643.3.131.1.1")
+ )[0].value
+ == "007710474375"
+ )
@pytest.mark.skipif(
backend._lib.Cryptography_HAS_EVP_PKEY_DHX == 1,
- reason="Requires OpenSSL without EVP_PKEY_DHX (< 1.0.2)")
+ reason="Requires OpenSSL without EVP_PKEY_DHX (< 1.0.2)",
+)
@pytest.mark.requires_backend_interface(interface=DHBackend)
class TestOpenSSLDHSerialization(object):
-
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
- os.path.join("asymmetric", "DH", "RFC5114.txt"),
- load_nist_vectors))
+ os.path.join("asymmetric", "DH", "RFC5114.txt"), load_nist_vectors
+ ),
+ )
def test_dh_serialization_with_q_unsupported(self, backend, vector):
- parameters = dh.DHParameterNumbers(int(vector["p"], 16),
- int(vector["g"], 16),
- int(vector["q"], 16))
+ parameters = dh.DHParameterNumbers(
+ int(vector["p"], 16), int(vector["g"], 16), int(vector["q"], 16)
+ )
public = dh.DHPublicNumbers(int(vector["ystatcavs"], 16), parameters)
private = dh.DHPrivateNumbers(int(vector["xstatcavs"], 16), public)
private_key = private.private_key(backend)
public_key = private_key.public_key()
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
- private_key.private_bytes(serialization.Encoding.PEM,
- serialization.PrivateFormat.PKCS8,
- serialization.NoEncryption())
+ private_key.private_bytes(
+ serialization.Encoding.PEM,
+ serialization.PrivateFormat.PKCS8,
+ serialization.NoEncryption(),
+ )
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
public_key.public_bytes(
serialization.Encoding.PEM,
- serialization.PublicFormat.SubjectPublicKeyInfo)
+ serialization.PublicFormat.SubjectPublicKeyInfo,
+ )
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
parameters.parameters(backend).parameter_bytes(
- serialization.Encoding.PEM,
- serialization.ParameterFormat.PKCS3)
+ serialization.Encoding.PEM, serialization.ParameterFormat.PKCS3
+ )
@pytest.mark.parametrize(
("key_path", "loader_func"),
@@ -585,14 +648,14 @@ class TestOpenSSLDHSerialization(object):
(
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.der"),
serialization.load_der_private_key,
- )
- ]
+ ),
+ ],
)
- def test_private_load_dhx_unsupported(self, key_path, loader_func,
- backend):
+ def test_private_load_dhx_unsupported(
+ self, key_path, loader_func, backend
+ ):
key_bytes = load_vectors_from_file(
- key_path,
- lambda pemfile: pemfile.read(), mode="rb"
+ key_path, lambda pemfile: pemfile.read(), mode="rb"
)
with pytest.raises(ValueError):
loader_func(key_bytes, None, backend)
@@ -607,14 +670,12 @@ class TestOpenSSLDHSerialization(object):
(
os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.der"),
serialization.load_der_public_key,
- )
- ]
+ ),
+ ],
)
- def test_public_load_dhx_unsupported(self, key_path, loader_func,
- backend):
+ def test_public_load_dhx_unsupported(self, key_path, loader_func, backend):
key_bytes = load_vectors_from_file(
- key_path,
- lambda pemfile: pemfile.read(), mode="rb"
+ key_path, lambda pemfile: pemfile.read(), mode="rb"
)
with pytest.raises(ValueError):
loader_func(key_bytes, backend)
diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py
index 1db103b5e..d8bc8660a 100644
--- a/tests/hazmat/backends/test_openssl_memleak.py
+++ b/tests/hazmat/backends/test_openssl_memleak.py
@@ -128,7 +128,9 @@ def assert_no_memory_leaks(s, argv=[]):
env = os.environ.copy()
env["PYTHONPATH"] = os.pathsep.join(sys.path)
argv = [
- sys.executable, "-c", "{0}\n\n{1}".format(s, MEMORY_LEAK_SCRIPT)
+ sys.executable,
+ "-c",
+ "{}\n\n{}".format(s, MEMORY_LEAK_SCRIPT),
] + argv
# Shell out to a fresh Python process because OpenSSL does not allow you to
# install new memory hooks after the first malloc/free occurs.
@@ -156,62 +158,86 @@ def assert_no_memory_leaks(s, argv=[]):
def skip_if_memtesting_not_supported():
return pytest.mark.skipif(
not Binding().lib.Cryptography_HAS_MEM_FUNCTIONS,
- reason="Requires OpenSSL memory functions (>=1.1.0)"
+ reason="Requires OpenSSL memory functions (>=1.1.0)",
)
+@pytest.mark.skip_fips(reason="FIPS self-test sets allow_customize = 0")
@skip_if_memtesting_not_supported()
class TestAssertNoMemoryLeaks(object):
def test_no_leak_no_malloc(self):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
pass
- """))
+ """
+ )
+ )
def test_no_leak_free(self):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
from cryptography.hazmat.bindings.openssl.binding import Binding
b = Binding()
name = b.lib.X509_NAME_new()
b.lib.X509_NAME_free(name)
- """))
+ """
+ )
+ )
def test_no_leak_gc(self):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
from cryptography.hazmat.bindings.openssl.binding import Binding
b = Binding()
name = b.lib.X509_NAME_new()
b.ffi.gc(name, b.lib.X509_NAME_free)
- """))
+ """
+ )
+ )
def test_leak(self):
with pytest.raises(AssertionError):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
from cryptography.hazmat.bindings.openssl.binding import (
Binding
)
b = Binding()
b.lib.X509_NAME_new()
- """))
+ """
+ )
+ )
def test_errors(self):
with pytest.raises(ValueError):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
raise ZeroDivisionError
- """))
+ """
+ )
+ )
+@pytest.mark.skip_fips(reason="FIPS self-test sets allow_customize = 0")
@skip_if_memtesting_not_supported()
class TestOpenSSLMemoryLeaks(object):
- @pytest.mark.parametrize("path", [
- "x509/PKITS_data/certs/ValidcRLIssuerTest28EE.crt",
- ])
- def test_x509_certificate_extensions(self, path):
- assert_no_memory_leaks(textwrap.dedent("""
+ @pytest.mark.parametrize(
+ "path", ["x509/PKITS_data/certs/ValidcRLIssuerTest28EE.crt"]
+ )
+ def test_der_x509_certificate_extensions(self, path):
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func(path):
from cryptography import x509
from cryptography.hazmat.backends.openssl import backend
@@ -224,10 +250,37 @@ class TestOpenSSLMemoryLeaks(object):
)
cert.extensions
- """), [path])
+ """
+ ),
+ [path],
+ )
+
+ @pytest.mark.parametrize("path", ["x509/cryptography.io.pem"])
+ def test_pem_x509_certificate_extensions(self, path):
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
+ def func(path):
+ from cryptography import x509
+ from cryptography.hazmat.backends.openssl import backend
+
+ import cryptography_vectors
+
+ with cryptography_vectors.open_vector_file(path, "rb") as f:
+ cert = x509.load_pem_x509_certificate(
+ f.read(), backend
+ )
+
+ cert.extensions
+ """
+ ),
+ [path],
+ )
def test_x509_csr_extensions(self):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
from cryptography import x509
from cryptography.hazmat.backends.openssl import backend
@@ -244,10 +297,14 @@ class TestOpenSSLMemoryLeaks(object):
).sign(private_key, hashes.SHA256(), backend)
cert.extensions
- """))
+ """
+ )
+ )
def test_ec_private_numbers_private_key(self):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
from cryptography.hazmat.backends.openssl import backend
from cryptography.hazmat.primitives.asymmetric import ec
@@ -269,26 +326,38 @@ class TestOpenSSLMemoryLeaks(object):
)
)
).private_key(backend)
- """))
+ """
+ )
+ )
def test_ec_derive_private_key(self):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
from cryptography.hazmat.backends.openssl import backend
from cryptography.hazmat.primitives.asymmetric import ec
ec.derive_private_key(1, ec.SECP256R1(), backend)
- """))
+ """
+ )
+ )
def test_x25519_pubkey_from_private_key(self):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
from cryptography.hazmat.primitives.asymmetric import x25519
private_key = x25519.X25519PrivateKey.generate()
private_key.public_key()
- """))
+ """
+ )
+ )
def test_create_ocsp_request(self):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
from cryptography import x509
from cryptography.hazmat.backends.openssl import backend
@@ -306,14 +375,18 @@ class TestOpenSSLMemoryLeaks(object):
cert, cert, hashes.SHA1()
).add_extension(x509.OCSPNonce(b"0000"), False)
req = builder.build()
- """))
+ """
+ )
+ )
- @pytest.mark.parametrize("path", [
- "pkcs12/cert-aes256cbc-no-key.p12",
- "pkcs12/cert-key-aes256cbc.p12",
- ])
+ @pytest.mark.parametrize(
+ "path",
+ ["pkcs12/cert-aes256cbc-no-key.p12", "pkcs12/cert-key-aes256cbc.p12"],
+ )
def test_load_pkcs12_key_and_certificates(self, path):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func(path):
from cryptography import x509
from cryptography.hazmat.backends.openssl import backend
@@ -324,10 +397,15 @@ class TestOpenSSLMemoryLeaks(object):
pkcs12.load_key_and_certificates(
f.read(), b"cryptography", backend
)
- """), [path])
+ """
+ ),
+ [path],
+ )
def test_create_crl_with_idp(self):
- assert_no_memory_leaks(textwrap.dedent("""
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
def func():
import datetime
from cryptography import x509
@@ -369,4 +447,109 @@ class TestOpenSSLMemoryLeaks(object):
crl.extensions.get_extension_for_class(
x509.IssuingDistributionPoint
)
- """))
+ """
+ )
+ )
+
+ def test_create_certificate_with_extensions(self):
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
+ def func():
+ import datetime
+
+ from cryptography import x509
+ from cryptography.hazmat.backends.openssl import backend
+ from cryptography.hazmat.primitives import hashes
+ from cryptography.hazmat.primitives.asymmetric import ec
+ from cryptography.x509.oid import (
+ AuthorityInformationAccessOID, ExtendedKeyUsageOID, NameOID
+ )
+
+ private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+
+ not_valid_before = datetime.datetime.now()
+ not_valid_after = not_valid_before + datetime.timedelta(days=365)
+
+ aia = x509.AuthorityInformationAccess([
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
+ )
+ ])
+ sans = [u'*.example.org', u'foobar.example.net']
+ san = x509.SubjectAlternativeName(list(map(x509.DNSName, sans)))
+
+ ski = x509.SubjectKeyIdentifier.from_public_key(
+ private_key.public_key()
+ )
+ eku = x509.ExtendedKeyUsage([
+ ExtendedKeyUsageOID.CLIENT_AUTH,
+ ExtendedKeyUsageOID.SERVER_AUTH,
+ ExtendedKeyUsageOID.CODE_SIGNING,
+ ])
+
+ builder = x509.CertificateBuilder().serial_number(
+ 777
+ ).issuer_name(x509.Name([
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+ ])).subject_name(x509.Name([
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+ ])).public_key(
+ private_key.public_key()
+ ).add_extension(
+ aia, critical=False
+ ).not_valid_before(
+ not_valid_before
+ ).not_valid_after(
+ not_valid_after
+ )
+
+ cert = builder.sign(private_key, hashes.SHA256(), backend)
+ cert.extensions
+ """
+ )
+ )
+
+ def test_write_pkcs12_key_and_certificates(self):
+ assert_no_memory_leaks(
+ textwrap.dedent(
+ """
+ def func():
+ import os
+ from cryptography import x509
+ from cryptography.hazmat.backends.openssl import backend
+ from cryptography.hazmat.primitives import serialization
+ from cryptography.hazmat.primitives.serialization import pkcs12
+ import cryptography_vectors
+
+ path = os.path.join('x509', 'custom', 'ca', 'ca.pem')
+ with cryptography_vectors.open_vector_file(path, "rb") as f:
+ cert = x509.load_pem_x509_certificate(
+ f.read(), backend
+ )
+ path2 = os.path.join('x509', 'custom', 'dsa_selfsigned_ca.pem')
+ with cryptography_vectors.open_vector_file(path2, "rb") as f:
+ cert2 = x509.load_pem_x509_certificate(
+ f.read(), backend
+ )
+ path3 = os.path.join('x509', 'letsencryptx3.pem')
+ with cryptography_vectors.open_vector_file(path3, "rb") as f:
+ cert3 = x509.load_pem_x509_certificate(
+ f.read(), backend
+ )
+ key_path = os.path.join("x509", "custom", "ca", "ca_key.pem")
+ with cryptography_vectors.open_vector_file(key_path, "rb") as f:
+ key = serialization.load_pem_private_key(
+ f.read(), None, backend
+ )
+ encryption = serialization.NoEncryption()
+ pkcs12.serialize_key_and_certificates(
+ b"name", key, cert, [cert2, cert3], encryption)
+ """
+ )
+ )
diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py
index fb1e62fa9..4bc046b80 100644
--- a/tests/hazmat/bindings/test_openssl.py
+++ b/tests/hazmat/bindings/test_openssl.py
@@ -8,7 +8,10 @@ import pytest
from cryptography.exceptions import InternalError
from cryptography.hazmat.bindings.openssl.binding import (
- Binding, _consume_errors, _openssl_assert
+ Binding,
+ _consume_errors,
+ _openssl_assert,
+ _verify_package_version,
)
@@ -19,18 +22,6 @@ class TestOpenSSL(object):
assert binding.lib
assert binding.ffi
- def test_crypto_lock_init(self):
- b = Binding()
-
- b.init_static_locks()
- lock_cb = b.lib.CRYPTO_get_locking_callback()
- if b.lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER:
- assert lock_cb == b.ffi.NULL
- assert b.lib.Cryptography_HAS_LOCKING_CALLBACKS == 0
- else:
- assert lock_cb != b.ffi.NULL
- assert b.lib.Cryptography_HAS_LOCKING_CALLBACKS == 1
-
def test_add_engine_more_than_once(self):
b = Binding()
b._register_osrandom_engine()
@@ -82,7 +73,7 @@ class TestOpenSSL(object):
def test_conditional_removal(self):
b = Binding()
- if b.lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER:
+ if not b.lib.CRYPTOGRAPHY_IS_LIBRESSL:
assert b.lib.TLS_ST_OK
else:
with pytest.raises(AttributeError):
@@ -95,7 +86,7 @@ class TestOpenSSL(object):
b.lib.EVP_F_EVP_ENCRYPTFINAL_EX,
b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,
b"",
- -1
+ -1,
)
with pytest.raises(InternalError) as exc_info:
_openssl_assert(b.lib, False)
@@ -114,7 +105,11 @@ class TestOpenSSL(object):
b.lib.EVP_F_EVP_ENCRYPTFINAL_EX,
b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,
b"",
- -1
+ -1,
)
b._register_osrandom_engine()
assert _consume_errors(b.lib) == []
+
+ def test_version_mismatch(self):
+ with pytest.raises(ImportError):
+ _verify_package_version("nottherightversion")
diff --git a/tests/hazmat/primitives/fixtures_dh.py b/tests/hazmat/primitives/fixtures_dh.py
new file mode 100644
index 000000000..b766c4265
--- /dev/null
+++ b/tests/hazmat/primitives/fixtures_dh.py
@@ -0,0 +1,26 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+from cryptography.hazmat.primitives.asymmetric import dh
+
+FFDH3072_P = dh.DHParameterNumbers(
+ p=int(
+ "ffffffffffffffffadf85458a2bb4a9aafdc5620273d3cf1d8b9c583ce2d3695a9e"
+ "13641146433fbcc939dce249b3ef97d2fe363630c75d8f681b202aec4617ad3df1e"
+ "d5d5fd65612433f51f5f066ed0856365553ded1af3b557135e7f57c935984f0c70e"
+ "0e68b77e2a689daf3efe8721df158a136ade73530acca4f483a797abc0ab182b324"
+ "fb61d108a94bb2c8e3fbb96adab760d7f4681d4f42a3de394df4ae56ede76372bb1"
+ "90b07a7c8ee0a6d709e02fce1cdf7e2ecc03404cd28342f619172fe9ce98583ff8e"
+ "4f1232eef28183c3fe3b1b4c6fad733bb5fcbc2ec22005c58ef1837d1683b2c6f34"
+ "a26c1b2effa886b4238611fcfdcde355b3b6519035bbc34f4def99c023861b46fc9"
+ "d6e6c9077ad91d2691f7f7ee598cb0fac186d91caefe130985139270b4130c93bc4"
+ "37944f4fd4452e2d74dd364f2e21e71f54bff5cae82ab9c9df69ee86d2bc522363a"
+ "0dabc521979b0deada1dbf9a42d5c4484e0abcd06bfa53ddef3c1b20ee3fd59d7c2"
+ "5e41d2b66c62e37ffffffffffffffff",
+ 16,
+ ),
+ g=2,
+)
diff --git a/tests/hazmat/primitives/fixtures_dsa.py b/tests/hazmat/primitives/fixtures_dsa.py
index dd947ae82..d4568ead7 100644
--- a/tests/hazmat/primitives/fixtures_dsa.py
+++ b/tests/hazmat/primitives/fixtures_dsa.py
@@ -5,7 +5,9 @@
from __future__ import absolute_import, division, print_function
from cryptography.hazmat.primitives.asymmetric.dsa import (
- DSAParameterNumbers, DSAPrivateNumbers, DSAPublicNumbers
+ DSAParameterNumbers,
+ DSAPrivateNumbers,
+ DSAPublicNumbers,
)
@@ -13,140 +15,147 @@ DSA_KEY_1024 = DSAPrivateNumbers(
public_numbers=DSAPublicNumbers(
parameter_numbers=DSAParameterNumbers(
p=int(
- 'd38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef34'
- '1eabb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae7912102b6'
- 'b502e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189cef'
- '1ace778d7845a5c1c1c7147123188f8dc551054ee162b634d60f097f7'
- '19076640e20980a0093113a8bd73', 16
+ "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef34"
+ "1eabb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae7912102b6"
+ "b502e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189cef"
+ "1ace778d7845a5c1c1c7147123188f8dc551054ee162b634d60f097f7"
+ "19076640e20980a0093113a8bd73",
+ 16,
),
- q=int('96c5390a8b612c0e422bb2b0ea194a3ec935a281', 16),
+ q=int("96c5390a8b612c0e422bb2b0ea194a3ec935a281", 16),
g=int(
- '06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce499'
- '1d2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d30'
- '0042bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34c'
- 'd12615474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f4'
- 'fd9f93cd6f4f17fc076341a7e7d9', 16
- )
+ "06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce499"
+ "1d2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d30"
+ "0042bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34c"
+ "d12615474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f4"
+ "fd9f93cd6f4f17fc076341a7e7d9",
+ 16,
+ ),
),
y=int(
- '6f26d98d41de7d871b6381851c9d91fa03942092ab6097e76422070edb71d'
- 'b44ff568280fdb1709f8fc3feab39f1f824adaeb2a298088156ac31af1aa0'
- '4bf54f475bdcfdcf2f8a2dd973e922d83e76f016558617603129b21c70bf7'
- 'd0e5dc9e68fe332e295b65876eb9a12fe6fca9f1a1ce80204646bf99b5771'
- 'd249a6fea627', 16
- )
+ "6f26d98d41de7d871b6381851c9d91fa03942092ab6097e76422070edb71d"
+ "b44ff568280fdb1709f8fc3feab39f1f824adaeb2a298088156ac31af1aa0"
+ "4bf54f475bdcfdcf2f8a2dd973e922d83e76f016558617603129b21c70bf7"
+ "d0e5dc9e68fe332e295b65876eb9a12fe6fca9f1a1ce80204646bf99b5771"
+ "d249a6fea627",
+ 16,
+ ),
),
- x=int('8185fee9cc7c0e91fd85503274f1cd5a3fd15a49', 16)
+ x=int("8185fee9cc7c0e91fd85503274f1cd5a3fd15a49", 16),
)
DSA_KEY_2048 = DSAPrivateNumbers(
public_numbers=DSAPublicNumbers(
parameter_numbers=DSAParameterNumbers(
p=int(
- 'ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace5e9c4'
- '1434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17dac62c98e70'
- '6af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b12252c40278fff'
- '9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d244e54561b0'
- 'dca39b301de8c49da9fb23df33c6182e3f983208c560fb5119fbf78eb'
- 'e3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a2b4f0e9e3'
- 'd9dbac122f750dd754325135257488b1f6ecabf21bff2947fe0d3b2cb'
- '7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a908c36e9'
- '5e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac5aa66ef7',
- 16
+ "ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace5e9c4"
+ "1434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17dac62c98e70"
+ "6af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b12252c40278fff"
+ "9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d244e54561b0"
+ "dca39b301de8c49da9fb23df33c6182e3f983208c560fb5119fbf78eb"
+ "e3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a2b4f0e9e3"
+ "d9dbac122f750dd754325135257488b1f6ecabf21bff2947fe0d3b2cb"
+ "7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a908c36e9"
+ "5e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac5aa66ef7",
+ 16,
),
q=int(
- '8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b18f507'
- '192c19d', 16
+ "8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b18f507"
+ "192c19d",
+ 16,
),
g=int(
- 'e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b1'
- '913413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9'
- '8076739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908b'
- 'ae03e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d555'
- '1b2fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c6156'
- '8f78d0706b10a26f23b4f197c322b825002284a0aca91807bba98ece9'
- '12b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f840387'
- '3d12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed27'
- '3b146ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302',
- 16
- )
+ "e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b1"
+ "913413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9"
+ "8076739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908b"
+ "ae03e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d555"
+ "1b2fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c6156"
+ "8f78d0706b10a26f23b4f197c322b825002284a0aca91807bba98ece9"
+ "12b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f840387"
+ "3d12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed27"
+ "3b146ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302",
+ 16,
+ ),
),
y=int(
- '6b32e31ab9031dc4dd0b5039a78d07826687ab087ae6de4736f5b0434e125'
- '3092e8a0b231f9c87f3fc8a4cb5634eb194bf1b638b7a7889620ce6711567'
- 'e36aa36cda4604cfaa601a45918371d4ccf68d8b10a50a0460eb1dc0fff62'
- 'ef5e6ee4d473e18ea4a66c196fb7e677a49b48241a0b4a97128eff30fa437'
- '050501a584f8771e7280d26d5af30784039159c11ebfea10b692fd0a58215'
- 'eeb18bff117e13f08db792ed4151a218e4bed8dddfb0793225bd1e9773505'
- '166f4bd8cedbb286ea28232972da7bae836ba97329ba6b0a36508e50a52a7'
- '675e476d4d4137eae13f22a9d2fefde708ba8f34bf336c6e76331761e4b06'
- '17633fe7ec3f23672fb19d27', 16
- )
+ "6b32e31ab9031dc4dd0b5039a78d07826687ab087ae6de4736f5b0434e125"
+ "3092e8a0b231f9c87f3fc8a4cb5634eb194bf1b638b7a7889620ce6711567"
+ "e36aa36cda4604cfaa601a45918371d4ccf68d8b10a50a0460eb1dc0fff62"
+ "ef5e6ee4d473e18ea4a66c196fb7e677a49b48241a0b4a97128eff30fa437"
+ "050501a584f8771e7280d26d5af30784039159c11ebfea10b692fd0a58215"
+ "eeb18bff117e13f08db792ed4151a218e4bed8dddfb0793225bd1e9773505"
+ "166f4bd8cedbb286ea28232972da7bae836ba97329ba6b0a36508e50a52a7"
+ "675e476d4d4137eae13f22a9d2fefde708ba8f34bf336c6e76331761e4b06"
+ "17633fe7ec3f23672fb19d27",
+ 16,
+ ),
),
x=int(
- '405772da6e90d809e77d5de796562a2dd4dfd10ef00a83a3aba6bd818a0348a1',
- 16
- )
+ "405772da6e90d809e77d5de796562a2dd4dfd10ef00a83a3aba6bd818a0348a1", 16
+ ),
)
DSA_KEY_3072 = DSAPrivateNumbers(
public_numbers=DSAPublicNumbers(
parameter_numbers=DSAParameterNumbers(
p=int(
- 'f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d582'
- '8c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a84'
- '2ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e'
- '80abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84e'
- 'c389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea265'
- '1b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a142'
- '85a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab060'
- '548de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba'
- '9844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1'
- 'd54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818'
- 'f06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673'
- 'ae4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f747'
- '6cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c1'
- '136f303f4b4d25ad5b692229957', 16
+ "f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d582"
+ "8c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a84"
+ "2ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e"
+ "80abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84e"
+ "c389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea265"
+ "1b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a142"
+ "85a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab060"
+ "548de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba"
+ "9844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1"
+ "d54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818"
+ "f06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673"
+ "ae4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f747"
+ "6cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c1"
+ "136f303f4b4d25ad5b692229957",
+ 16,
),
q=int(
- 'd3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210f6169'
- '041653b', 16
+ "d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210f6169"
+ "041653b",
+ 16,
),
g=int(
- 'ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978db2104'
- 'd7394b493c18332c64cec906a71c3778bd93341165dee8e6cd4ca6f13'
- 'afff531191194ada55ecf01ff94d6cf7c4768b82dd29cd131aaf202ae'
- 'fd40e564375285c01f3220af4d70b96f1395420d778228f1461f5d0b8'
- 'e47357e87b1fe3286223b553e3fc9928f16ae3067ded6721bedf1d1a0'
- '1bfd22b9ae85fce77820d88cdf50a6bde20668ad77a707d1c60fcc5d5'
- '1c9de488610d0285eb8ff721ff141f93a9fb23c1d1f7654c07c46e588'
- '36d1652828f71057b8aff0b0778ef2ca934ea9d0f37daddade2d823a4'
- 'd8e362721082e279d003b575ee59fd050d105dfd71cd63154efe431a0'
- '869178d9811f4f231dc5dcf3b0ec0f2b0f9896c32ec6c7ee7d60aa971'
- '09e09224907328d4e6acd10117e45774406c4c947da8020649c3168f6'
- '90e0bd6e91ac67074d1d436b58ae374523deaf6c93c1e6920db4a080b'
- '744804bb073cecfe83fa9398cf150afa286dc7eb7949750cf5001ce10'
- '4e9187f7e16859afa8fd0d775ae', 16
- )
+ "ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978db2104"
+ "d7394b493c18332c64cec906a71c3778bd93341165dee8e6cd4ca6f13"
+ "afff531191194ada55ecf01ff94d6cf7c4768b82dd29cd131aaf202ae"
+ "fd40e564375285c01f3220af4d70b96f1395420d778228f1461f5d0b8"
+ "e47357e87b1fe3286223b553e3fc9928f16ae3067ded6721bedf1d1a0"
+ "1bfd22b9ae85fce77820d88cdf50a6bde20668ad77a707d1c60fcc5d5"
+ "1c9de488610d0285eb8ff721ff141f93a9fb23c1d1f7654c07c46e588"
+ "36d1652828f71057b8aff0b0778ef2ca934ea9d0f37daddade2d823a4"
+ "d8e362721082e279d003b575ee59fd050d105dfd71cd63154efe431a0"
+ "869178d9811f4f231dc5dcf3b0ec0f2b0f9896c32ec6c7ee7d60aa971"
+ "09e09224907328d4e6acd10117e45774406c4c947da8020649c3168f6"
+ "90e0bd6e91ac67074d1d436b58ae374523deaf6c93c1e6920db4a080b"
+ "744804bb073cecfe83fa9398cf150afa286dc7eb7949750cf5001ce10"
+ "4e9187f7e16859afa8fd0d775ae",
+ 16,
+ ),
),
y=int(
- '814824e435e1e6f38daa239aad6dad21033afce6a3ebd35c1359348a0f241'
- '8871968c2babfc2baf47742148828f8612183178f126504da73566b6bab33'
- 'ba1f124c15aa461555c2451d86c94ee21c3e3fc24c55527e01b1f03adcdd8'
- 'ec5cb08082803a7b6a829c3e99eeb332a2cf5c035b0ce0078d3d414d31fa4'
- '7e9726be2989b8d06da2e6cd363f5a7d1515e3f4925e0b32adeae3025cc5a'
- '996f6fd27494ea408763de48f3bb39f6a06514b019899b312ec570851637b'
- '8865cff3a52bf5d54ad5a19e6e400a2d33251055d0a440b50d53f4791391d'
- 'c754ad02b9eab74c46b4903f9d76f824339914db108057af7cde657d41766'
- 'a99991ac8787694f4185d6f91d7627048f827b405ec67bf2fe56141c4c581'
- 'd8c317333624e073e5879a82437cb0c7b435c0ce434e15965db1315d64895'
- '991e6bbe7dac040c42052408bbc53423fd31098248a58f8a67da3a39895cd'
- '0cc927515d044c1e3cb6a3259c3d0da354cce89ea3552c59609db10ee9899'
- '86527436af21d9485ddf25f90f7dff6d2bae', 16
- )
+ "814824e435e1e6f38daa239aad6dad21033afce6a3ebd35c1359348a0f241"
+ "8871968c2babfc2baf47742148828f8612183178f126504da73566b6bab33"
+ "ba1f124c15aa461555c2451d86c94ee21c3e3fc24c55527e01b1f03adcdd8"
+ "ec5cb08082803a7b6a829c3e99eeb332a2cf5c035b0ce0078d3d414d31fa4"
+ "7e9726be2989b8d06da2e6cd363f5a7d1515e3f4925e0b32adeae3025cc5a"
+ "996f6fd27494ea408763de48f3bb39f6a06514b019899b312ec570851637b"
+ "8865cff3a52bf5d54ad5a19e6e400a2d33251055d0a440b50d53f4791391d"
+ "c754ad02b9eab74c46b4903f9d76f824339914db108057af7cde657d41766"
+ "a99991ac8787694f4185d6f91d7627048f827b405ec67bf2fe56141c4c581"
+ "d8c317333624e073e5879a82437cb0c7b435c0ce434e15965db1315d64895"
+ "991e6bbe7dac040c42052408bbc53423fd31098248a58f8a67da3a39895cd"
+ "0cc927515d044c1e3cb6a3259c3d0da354cce89ea3552c59609db10ee9899"
+ "86527436af21d9485ddf25f90f7dff6d2bae",
+ 16,
+ ),
),
x=int(
- 'b2764c46113983777d3e7e97589f1303806d14ad9f2f1ef033097de954b17706',
- 16
- )
+ "b2764c46113983777d3e7e97589f1303806d14ad9f2f1ef033097de954b17706", 16
+ ),
)
diff --git a/tests/hazmat/primitives/fixtures_ec.py b/tests/hazmat/primitives/fixtures_ec.py
index 21c690317..d1d0a46ff 100644
--- a/tests/hazmat/primitives/fixtures_ec.py
+++ b/tests/hazmat/primitives/fixtures_ec.py
@@ -9,288 +9,272 @@ from cryptography.hazmat.primitives.asymmetric import ec
EC_KEY_SECT571R1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '213997069697108634621868251335076179190383272087548888968788698953'
- '131928375431570122753130054966269038244076049869476736547896549201'
- '7388482714521707824160638375437887802901'
+ "213997069697108634621868251335076179190383272087548888968788698953"
+ "131928375431570122753130054966269038244076049869476736547896549201"
+ "7388482714521707824160638375437887802901"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT571R1(),
x=int(
- '42585672410900520895287019432267514156432686681290164230262278'
- '54789182447139054594501570747809649335533486119017169439209005'
- '883737780433424425566023654583165324498640038089'
+ "42585672410900520895287019432267514156432686681290164230262278"
+ "54789182447139054594501570747809649335533486119017169439209005"
+ "883737780433424425566023654583165324498640038089"
),
y=int(
- '13822523320209387572500458104799806851658024537477228250738334'
- '46977851514777531296572763848253279034733550774927720436494321'
- '97281333379623823457479233585424800362717541750'
- )
- )
+ "13822523320209387572500458104799806851658024537477228250738334"
+ "46977851514777531296572763848253279034733550774927720436494321"
+ "97281333379623823457479233585424800362717541750"
+ ),
+ ),
)
EC_KEY_SECT409R1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '604993237916498765317587097853603474519114726157206838874832379003'
- '281871982139714656205843929472002062791572217653118715727'
+ "604993237916498765317587097853603474519114726157206838874832379003"
+ "281871982139714656205843929472002062791572217653118715727"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT409R1(),
x=int(
- '76237701339268928039087238870073679814646664010783544301589269'
- '2272579213400205907766385199643053767195204247826349822350081'
+ "76237701339268928039087238870073679814646664010783544301589269"
+ "2272579213400205907766385199643053767195204247826349822350081"
),
y=int(
- '10056668929618383045204866060110626563392345494925302478351744'
- '01475129090774493235522729123877384838835703483224447476728811'
- )
- )
+ "10056668929618383045204866060110626563392345494925302478351744"
+ "01475129090774493235522729123877384838835703483224447476728811"
+ ),
+ ),
)
EC_KEY_SECT283R1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '589705077255658434962118789801402573495547207239917043241273753671'
- '0603230261342427657'
+ "589705077255658434962118789801402573495547207239917043241273753671"
+ "0603230261342427657"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT283R1(),
x=int(
- '10694213430317013187241490088760888472172922291550831393222973'
- '531614941756901942108493'
+ "10694213430317013187241490088760888472172922291550831393222973"
+ "531614941756901942108493"
),
y=int(
- '11461553100313943515373601367527399649593366728262918214942116'
- '4359557613202950705170'
- )
- )
+ "11461553100313943515373601367527399649593366728262918214942116"
+ "4359557613202950705170"
+ ),
+ ),
)
EC_KEY_SECT233R1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '343470067105388144757135261232658742142830154753739648095101899829'
- '8288'
+ "343470067105388144757135261232658742142830154753739648095101899829"
+ "8288"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT233R1(),
x=int(
- '74494951569151557692195071465128140646140765188698294062550374'
- '71118267'
+ "74494951569151557692195071465128140646140765188698294062550374"
+ "71118267"
),
y=int(
- '48699150823022962508544923825876164485917001162461401797511748'
- '44872205'
- )
- )
+ "48699150823022962508544923825876164485917001162461401797511748"
+ "44872205"
+ ),
+ ),
)
EC_KEY_SECT163R2 = ec.EllipticCurvePrivateNumbers(
- private_value=int(
- '11788436193853888218177032687141056784083668635'
- ),
+ private_value=int("11788436193853888218177032687141056784083668635"),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT163R2(),
- x=int(
- '5247234453330640212490501030772203801908103222463'
- ),
- y=int(
- '3172513801099088785224248292142866317754124455206'
- )
- )
+ x=int("5247234453330640212490501030772203801908103222463"),
+ y=int("3172513801099088785224248292142866317754124455206"),
+ ),
)
EC_KEY_SECT571K1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '592811051234886966121888758661314648311634839499582476726008738218'
- '165015048237934517672316204181933804884636855291118594744334592153'
- '883208936227914544246799490897169723387'
+ "592811051234886966121888758661314648311634839499582476726008738218"
+ "165015048237934517672316204181933804884636855291118594744334592153"
+ "883208936227914544246799490897169723387"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT571K1(),
x=int(
- '81362471461936552203898455874182916939857774872643607884250052'
- '29301336524105230729653881789373412990921493551253481866317181'
- '50644729351721577822595637058949405764944491655'
+ "81362471461936552203898455874182916939857774872643607884250052"
+ "29301336524105230729653881789373412990921493551253481866317181"
+ "50644729351721577822595637058949405764944491655"
),
y=int(
- '14058041260812945396067821061063618047896814719828637241661260'
- '31235681542401975593036630733881695595289523801041910183736211'
- '587294494888450327374439795428519848065589000434'
- )
- )
+ "14058041260812945396067821061063618047896814719828637241661260"
+ "31235681542401975593036630733881695595289523801041910183736211"
+ "587294494888450327374439795428519848065589000434"
+ ),
+ ),
)
EC_KEY_SECT409K1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '110321743150399087059465162400463719641470113494908091197354523708'
- '934106732952992153105338671368548199643686444619485307877'
+ "110321743150399087059465162400463719641470113494908091197354523708"
+ "934106732952992153105338671368548199643686444619485307877"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT409K1(),
x=int(
- '62280214209410363493525178797944995742119600145953755916426161'
- '0790364158569265348038207313261547476506319796469776797725796'
+ "62280214209410363493525178797944995742119600145953755916426161"
+ "0790364158569265348038207313261547476506319796469776797725796"
),
y=int(
- '46653883749102474289095010108777579907422472804577185369332018'
- '7318642669590280811057512951467298158275464566214288556375885'
- )
- )
+ "46653883749102474289095010108777579907422472804577185369332018"
+ "7318642669590280811057512951467298158275464566214288556375885"
+ ),
+ ),
)
EC_KEY_SECT283K1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '182508394415444014156574733141549331538128234395356466108310015130'
- '3868915489347291850'
+ "182508394415444014156574733141549331538128234395356466108310015130"
+ "3868915489347291850"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT283K1(),
x=int(
- '31141647206111886426350703123670451554123180910379592764773885'
- '2959123367428352287032'
+ "31141647206111886426350703123670451554123180910379592764773885"
+ "2959123367428352287032"
),
y=int(
- '71787460144483665964585187837283963089964760704065205376175384'
- '58957627834444017112582'
- )
- )
+ "71787460144483665964585187837283963089964760704065205376175384"
+ "58957627834444017112582"
+ ),
+ ),
)
EC_KEY_SECT233K1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '172670089647474613734091436081960550801254775902629891892394471086'
- '2070'
+ "172670089647474613734091436081960550801254775902629891892394471086"
+ "2070"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT233K1(),
x=int(
- '55693911474339510991521579392202889561373678973929426354737048'
- '68129172'
+ "55693911474339510991521579392202889561373678973929426354737048"
+ "68129172"
),
y=int(
- '11025856248546376145959939911850923631416718241836051344384802'
- '737277815'
- )
- )
+ "11025856248546376145959939911850923631416718241836051344384802"
+ "737277815"
+ ),
+ ),
)
EC_KEY_SECT163K1 = ec.EllipticCurvePrivateNumbers(
- private_value=int(
- '3699303791425402204035307605170569820290317991287'
- ),
+ private_value=int("3699303791425402204035307605170569820290317991287"),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECT163K1(),
- x=int(
- '4479755902310063321544063130576409926980094120721'
- ),
- y=int(
- '3051218481937171839039826690648109285113977745779'
- )
- )
+ x=int("4479755902310063321544063130576409926980094120721"),
+ y=int("3051218481937171839039826690648109285113977745779"),
+ ),
)
EC_KEY_SECP521R1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '662751235215460886290293902658128847495347691199214706697089140769'
- '672273950767961331442265530524063943548846724348048614239791498442'
- '5997823106818915698960565'
+ "662751235215460886290293902658128847495347691199214706697089140769"
+ "672273950767961331442265530524063943548846724348048614239791498442"
+ "5997823106818915698960565"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECP521R1(),
x=int(
- '12944742826257420846659527752683763193401384271391513286022917'
- '29910013082920512632908350502247952686156279140016049549948975'
- '670668730618745449113644014505462'
+ "12944742826257420846659527752683763193401384271391513286022917"
+ "29910013082920512632908350502247952686156279140016049549948975"
+ "670668730618745449113644014505462"
),
y=int(
- '10784108810271976186737587749436295782985563640368689081052886'
- '16296815984553198866894145509329328086635278430266482551941240'
- '591605833440825557820439734509311'
- )
- )
+ "10784108810271976186737587749436295782985563640368689081052886"
+ "16296815984553198866894145509329328086635278430266482551941240"
+ "591605833440825557820439734509311"
+ ),
+ ),
)
EC_KEY_SECP384R1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '280814107134858470598753916394807521398239633534281633982576099083'
- '35787109896602102090002196616273211495718603965098'
+ "280814107134858470598753916394807521398239633534281633982576099083"
+ "35787109896602102090002196616273211495718603965098"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECP384R1(),
x=int(
- '10036914308591746758780165503819213553101287571902957054148542'
- '504671046744460374996612408381962208627004841444205030'
+ "10036914308591746758780165503819213553101287571902957054148542"
+ "504671046744460374996612408381962208627004841444205030"
),
y=int(
- '17337335659928075994560513699823544906448896792102247714689323'
- '575406618073069185107088229463828921069465902299522926'
- )
- )
+ "17337335659928075994560513699823544906448896792102247714689323"
+ "575406618073069185107088229463828921069465902299522926"
+ ),
+ ),
)
EC_KEY_SECP256R1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '271032978511595617649844168316234344656921218699414461240502635010'
- '25776962849'
+ "271032978511595617649844168316234344656921218699414461240502635010"
+ "25776962849"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECP256R1(),
x=int(
- '49325986169170464532722748935508337546545346352733747948730305'
- '442770101441241'
+ "49325986169170464532722748935508337546545346352733747948730305"
+ "442770101441241"
),
y=int(
- '51709162888529903487188595007092772817469799707382623884187518'
- '455962250433661'
- )
- )
+ "51709162888529903487188595007092772817469799707382623884187518"
+ "455962250433661"
+ ),
+ ),
)
EC_KEY_SECP256K1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '683341569008473593765879222774207677458810362976327530563215318048'
- '64380736732'
+ "683341569008473593765879222774207677458810362976327530563215318048"
+ "64380736732"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECP256K1(),
x=int(
- '59251322975795306609293064274738085741081547489119277536110995'
- '120127593127884'
+ "59251322975795306609293064274738085741081547489119277536110995"
+ "120127593127884"
),
y=int(
- '10334192001480392039227801832201340147605940717841294644187071'
- '8261641142297801'
- )
- )
+ "10334192001480392039227801832201340147605940717841294644187071"
+ "8261641142297801"
+ ),
+ ),
)
EC_KEY_SECP224R1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '234854340492774342642505519082413233282383066880756900834047566251'
- '50'
+ "234854340492774342642505519082413233282383066880756900834047566251"
+ "50"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECP224R1(),
x=int(
- '51165676638271204691095081341581621487998422645261573824239666'
- '1214'
+ "51165676638271204691095081341581621487998422645261573824239666"
+ "1214"
),
y=int(
- '14936601450555711309158397172719963843891926209168533453717969'
- '1265'
- )
- )
+ "14936601450555711309158397172719963843891926209168533453717969"
+ "1265"
+ ),
+ ),
)
EC_KEY_SECP192R1 = ec.EllipticCurvePrivateNumbers(
private_value=int(
- '4534766128536179420071447168915990251715442361606049349869'
+ "4534766128536179420071447168915990251715442361606049349869"
),
public_numbers=ec.EllipticCurvePublicNumbers(
curve=ec.SECP192R1(),
- x=int(
- '5415069751170397888083674339683360671310515485781457536999'
- ),
- y=int(
- '18671605334415960797751252911958331304288357195986572776'
- )
- )
+ x=int("5415069751170397888083674339683360671310515485781457536999"),
+ y=int("18671605334415960797751252911958331304288357195986572776"),
+ ),
)
diff --git a/tests/hazmat/primitives/fixtures_rsa.py b/tests/hazmat/primitives/fixtures_rsa.py
index a531783e5..2c0627282 100644
--- a/tests/hazmat/primitives/fixtures_rsa.py
+++ b/tests/hazmat/primitives/fixtures_rsa.py
@@ -5,7 +5,8 @@
from __future__ import absolute_import, division, print_function
from cryptography.hazmat.primitives.asymmetric.rsa import (
- RSAPrivateNumbers, RSAPublicNumbers
+ RSAPrivateNumbers,
+ RSAPublicNumbers,
)
@@ -18,7 +19,8 @@ RSA_KEY_512 = RSAPrivateNumbers(
),
d=int(
"272869352cacf9c866c4e107acc95d4c608ca91460a93d28588d51cfccc07f449"
- "18bbe7660f9f16adc2b4ed36ca310ef3d63b79bd447456e3505736a45a6ed21", 16
+ "18bbe7660f9f16adc2b4ed36ca310ef3d63b79bd447456e3505736a45a6ed21",
+ 16,
),
dmp1=int(
"addff2ec7564c6b64bc670d250b6f24b0b8db6b2810099813b7e7658cecf5c39", 16
@@ -34,178 +36,239 @@ RSA_KEY_512 = RSAPrivateNumbers(
n=int(
"ae5411f963c50e3267fafcf76381c8b1e5f7b741fdb2a544bcf48bd607b10c991"
"90caeb8011dc22cf83d921da55ec32bd05cac3ee02ca5e1dbef93952850b525",
- 16
+ 16,
),
- )
+ ),
)
RSA_KEY_512_ALT = RSAPrivateNumbers(
p=int(
- "febe19c29a0b50fefa4f7b1832f84df1caf9be8242da25c9d689e18226e67ce5",
- 16),
+ "febe19c29a0b50fefa4f7b1832f84df1caf9be8242da25c9d689e18226e67ce5", 16
+ ),
q=int(
- "eb616c639dd999feda26517e1c77b6878f363fe828c4e6670ec1787f28b1e731",
- 16),
+ "eb616c639dd999feda26517e1c77b6878f363fe828c4e6670ec1787f28b1e731", 16
+ ),
d=int(
"80edecfde704a806445a4cc782b85d3f36f17558f385654ea767f006470fdfcbda5e2"
- "206839289d3f419b4e4fb8e1acee1b4fb9c591f69b64ec83937f5829241", 16),
+ "206839289d3f419b4e4fb8e1acee1b4fb9c591f69b64ec83937f5829241",
+ 16,
+ ),
dmp1=int(
- "7f4fa06e2a3077a54691cc5216bf13ad40a4b9fa3dd0ea4bca259487484baea5",
- 16),
+ "7f4fa06e2a3077a54691cc5216bf13ad40a4b9fa3dd0ea4bca259487484baea5", 16
+ ),
dmq1=int(
- "35eaa70d5a8711c352ed1c15ab27b0e3f46614d575214535ae279b166597fac1",
- 16),
+ "35eaa70d5a8711c352ed1c15ab27b0e3f46614d575214535ae279b166597fac1", 16
+ ),
iqmp=int(
- "cc1f272de6846851ec80cb89a02dbac78f44b47bc08f53b67b4651a3acde8b19",
- 16),
+ "cc1f272de6846851ec80cb89a02dbac78f44b47bc08f53b67b4651a3acde8b19", 16
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
"ea397388b999ef0f7e7416fa000367efd9a0ba0deddd3f8160d1c36d62267f210"
"fbd9c97abeb6654450ff03e7601b8caa6c6f4cba18f0b52c179d17e8f258ad5",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_522 = RSAPrivateNumbers(
p=int(
"1a8aab9a069f92b52fdf05824f2846223dc27adfc806716a247a77d4c36885e4bf",
- 16),
+ 16,
+ ),
q=int(
"19e8d620d177ec54cdb733bb1915e72ef644b1202b889ceb524613efa49c07eb4f",
- 16),
+ 16,
+ ),
d=int(
"10b8a7c0a92c1ae2d678097d69db3bfa966b541fb857468291d48d1b52397ea2bac0d"
- "4370c159015c7219e3806a01bbafaffdd46f86e3da1e2d1fe80a0369ccd745", 16),
+ "4370c159015c7219e3806a01bbafaffdd46f86e3da1e2d1fe80a0369ccd745",
+ 16,
+ ),
dmp1=int(
- "3eb6277f66e6e2dcf89f1b8529431f730839dbd9a3e49555159bc8470eee886e5",
- 16),
+ "3eb6277f66e6e2dcf89f1b8529431f730839dbd9a3e49555159bc8470eee886e5", 16
+ ),
dmq1=int(
"184b4d74aa54c361e51eb23fee4eae5e4786b37b11b6e0447af9c0b9c4e4953c5b",
- 16),
+ 16,
+ ),
iqmp=int(
- "f80e9ab4fa7b35d0d232ef51c4736d1f2dcf2c7b1dd8716211b1bf1337e74f8ae",
- 16),
+ "f80e9ab4fa7b35d0d232ef51c4736d1f2dcf2c7b1dd8716211b1bf1337e74f8ae", 16
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
"2afaea0e0bb6fca037da7d190b5270a6c665bc18e7a456f7e69beaac4433db748"
"ba99acdd14697e453bca596eb35b47f2d48f1f85ef08ce5109dad557a9cf85ebf"
- "1", 16),
+ "1",
+ 16,
+ ),
),
)
RSA_KEY_599 = RSAPrivateNumbers(
p=int(
"cf95d20be0c7af69f4b3d909f65d858c26d1a7ef34da8e3977f4fa230580e58814b54"
- "24be99", 16),
+ "24be99",
+ 16,
+ ),
q=int(
"6052be4b28debd4265fe12ace5aa4a0c4eb8d63ff8853c66824b35622161eb48a3bc8"
- "c3ada5", 16),
+ "c3ada5",
+ 16,
+ ),
d=int(
"69d9adc465e61585d3142d7cc8dd30605e8d1cbbf31009bc2cd5538dc40528d5d68ee"
"fe6a42d23674b6ec76e192351bf368c8968f0392110bf1c2825dbcff071270b80adcc"
- "fa1d19d00a1", 16),
+ "fa1d19d00a1",
+ 16,
+ ),
dmp1=int(
"a86d10edde456687fba968b1f298d2e07226adb1221b2a466a93f3d83280f0bb46c20"
- "2b6811", 16),
+ "2b6811",
+ 16,
+ ),
dmq1=int(
"40d570e08611e6b1da94b95d46f8e7fe80be48f7a5ff8838375b08039514a399b11c2"
- "80735", 16),
+ "80735",
+ 16,
+ ),
iqmp=int(
"cd051cb0ea68b88765c041262ace2ec4db11dab14afd192742e34d5da3328637fabdf"
- "bae26e", 16),
+ "bae26e",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
"4e1b470fe00642426f3808e74c959632dd67855a4c503c5b7876ccf4dc7f6a1a4"
"9107b90d26daf0a7879a6858218345fbc6e59f01cd095ca5647c27c25265e6c47"
- "4fea89537191c7073d9d", 16),
- )
+ "4fea89537191c7073d9d",
+ 16,
+ ),
+ ),
)
RSA_KEY_745 = RSAPrivateNumbers(
p=int(
"1c5a0cfe9a86debd19eca33ba961f15bc598aa7983a545ce775b933afc89eb51bcf90"
- "836257fdd060d4b383240241d", 16
+ "836257fdd060d4b383240241d",
+ 16,
),
q=int(
"fb2634f657f82ee6b70553382c4e2ed26b947c97ce2f0016f1b282cf2998184ad0527"
- "a9eead826dd95fe06b57a025", 16
+ "a9eead826dd95fe06b57a025",
+ 16,
),
d=int(
"402f30f976bc07d15ff0779abff127b20a8b6b1d0024cc2ad8b6762d38f174f81e792"
"3b49d80bdbdd80d9675cbc7b2793ec199a0430eb5c84604dacfdb29259ae6a1a44676"
- "22f0b23d4cb0f5cb1db4b8173c8d9d3e57a74dbd200d2141", 16),
+ "22f0b23d4cb0f5cb1db4b8173c8d9d3e57a74dbd200d2141",
+ 16,
+ ),
dmp1=int(
"e5e95b7751a6649f199be21bef7a51c9e49821d945b6fc5f538b4a670d8762c375b00"
- "8e70f31d52b3ea2bd14c3101", 16),
+ "8e70f31d52b3ea2bd14c3101",
+ 16,
+ ),
dmq1=int(
"12b85d5843645f72990fcf8d2f58408b34b3a3b9d9078dd527fceb5d2fb7839008092"
- "dd4aca2a1fb00542801dcef5", 16),
+ "dd4aca2a1fb00542801dcef5",
+ 16,
+ ),
iqmp=int(
"5672740d947f621fc7969e3a44ec26736f3f819863d330e63e9409e139d20753551ac"
- "c16544dd2bdadb9dee917440", 16),
+ "c16544dd2bdadb9dee917440",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
"1bd085f92237774d34013b477ceebbb2f2feca71118db9b7429341477947e7b1d"
"04e8c43ede3c52bb25781af58d4ff81289f301eac62dc3bcd7dafd7a4d5304e9f"
- "308e766952fbf2b62373e66611fa53189987dbef9f7243dcbbeb25831", 16),
- )
+ "308e766952fbf2b62373e66611fa53189987dbef9f7243dcbbeb25831",
+ 16,
+ ),
+ ),
)
RSA_KEY_768 = RSAPrivateNumbers(
p=int(
"f80c0061b607f93206b68e208906498d68c6e396faf457150cf975c8f849848465869"
- "7ecd402313397088044c4c2071b", 16),
+ "7ecd402313397088044c4c2071b",
+ 16,
+ ),
q=int(
"e5b5dbecc93c6d306fc14e6aa9737f9be2728bc1a326a8713d2849b34c1cb54c63468"
- "3a68abb1d345dbf15a3c492cf55", 16),
+ "3a68abb1d345dbf15a3c492cf55",
+ 16,
+ ),
d=int(
"d44601442255ffa331212c60385b5e898555c75c0272632ff42d57c4b16ca97dbca9f"
"d6d99cd2c9fd298df155ed5141b4be06c651934076133331d4564d73faed7ce98e283"
- "2f7ce3949bc183be7e7ca34f6dd04a9098b6c73649394b0a76c541", 16),
+ "2f7ce3949bc183be7e7ca34f6dd04a9098b6c73649394b0a76c541",
+ 16,
+ ),
dmp1=int(
"a5763406fa0b65929661ce7b2b8c73220e43a5ebbfe99ff15ddf464fd238105ad4f2a"
- "c83818518d70627d8908703bb03", 16),
+ "c83818518d70627d8908703bb03",
+ 16,
+ ),
dmq1=int(
"cb467a9ef899a39a685aecd4d0ad27b0bfdc53b68075363c373d8eb2bed8eccaf3533"
- "42f4db735a9e087b7539c21ba9d", 16),
+ "42f4db735a9e087b7539c21ba9d",
+ 16,
+ ),
iqmp=int(
"5fe86bd3aee0c4d09ef11e0530a78a4534c9b833422813b5c934a450c8e564d8097a0"
- "6fd74f1ebe2d5573782093f587a", 16),
+ "6fd74f1ebe2d5573782093f587a",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
"de92f1eb5f4abf426b6cac9dd1e9bf57132a4988b4ed3f8aecc15e251028bd6df"
"46eb97c711624af7db15e6430894d1b640c13929329241ee094f5a4fe1a20bc9b"
"75232320a72bc567207ec54d6b48dccb19737cf63acc1021abb337f19130f7",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_1024 = RSAPrivateNumbers(
p=int(
"ea4d9d9a1a068be44b9a5f8f6de0512b2c5ba1fb804a4655babba688e6e890b347c1a"
- "7426685a929337f513ae4256f0b7e5022d642237f960c5b24b96bee8e51", 16),
+ "7426685a929337f513ae4256f0b7e5022d642237f960c5b24b96bee8e51",
+ 16,
+ ),
q=int(
"cffb33e400d6f08b410d69deb18a85cf0ed88fcca9f32d6f2f66c62143d49aff92c11"
- "4de937d4f1f62d4635ee89af99ce86d38a2b05310f3857c7b5d586ac8f9", 16),
+ "4de937d4f1f62d4635ee89af99ce86d38a2b05310f3857c7b5d586ac8f9",
+ 16,
+ ),
d=int(
"3d12d46d04ce942fb99be7bf30587b8cd3e21d75a2720e7bda1b867f1d418d91d8b9f"
"e1c00181fdde94f2faf33b4e6f800a1b3ae3b972ccb6d5079dcb6c794070ac8306d59"
"c00b58b7a9a81122a6b055832de7c72334a07494d8e7c9fbeed2cc37e011d9e6bfc6e"
- "9bcddbef7f0f5771d9cf82cd4b268c97ec684575c24b6c881", 16),
+ "9bcddbef7f0f5771d9cf82cd4b268c97ec684575c24b6c881",
+ 16,
+ ),
dmp1=int(
"470f2b11257b7ec9ca34136f487f939e6861920ad8a9ae132a02e74af5dceaa5b4c98"
- "2949ccb44b67e2bcad2f58674db237fe250e0d62b47b28fa1dfaa603b41", 16),
+ "2949ccb44b67e2bcad2f58674db237fe250e0d62b47b28fa1dfaa603b41",
+ 16,
+ ),
dmq1=int(
"c616e8317d6b3ae8272973709b80e8397256697ff14ea03389de454f619f99915a617"
- "45319fefbe154ec1d49441a772c2f63f7d15c478199afc60469bfd0d561", 16),
+ "45319fefbe154ec1d49441a772c2f63f7d15c478199afc60469bfd0d561",
+ 16,
+ ),
iqmp=int(
"d15e7c9ad357dfcd5dbdc8427680daf1006761bcfba93a7f86589ad88832a8d564b1c"
- "d4291a658c96fbaea7ca588795820902d85caebd49c2d731e3fe0243130", 16),
+ "d4291a658c96fbaea7ca588795820902d85caebd49c2d731e3fe0243130",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -213,31 +276,44 @@ RSA_KEY_1024 = RSAPrivateNumbers(
"ede07be3bed0e355d48e0dfab1e4fb5187adf42d7d3fb0401c082acb8481bf17f"
"0e871f8877be04c3a1197d40aa260e2e0c48ed3fd2b93dc3fc0867591f67f3cd6"
"0a77adee1d68a8c3730a5702485f6ac9ede7f0fd2918e037ee4cc1fc1b4c9",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_1025 = RSAPrivateNumbers(
p=int(
"18e9bfb7071725da04d31c103fa3563648c69def43a204989214eb57b0c8b299f9ef3"
- "5dda79a62d8d67fd2a9b69fbd8d0490aa2edc1e111a2b8eb7c737bb691a5", 16),
+ "5dda79a62d8d67fd2a9b69fbd8d0490aa2edc1e111a2b8eb7c737bb691a5",
+ 16,
+ ),
q=int(
"d8eccaeeb95815f3079d13685f3f72ca2bf2550b349518049421375df88ca9bbb4ba8"
- "cb0e3502203c9eeae174112509153445d251313e4711a102818c66fcbb7", 16),
+ "cb0e3502203c9eeae174112509153445d251313e4711a102818c66fcbb7",
+ 16,
+ ),
d=int(
"fe9ac54910b8b1bc948a03511c54cab206a1d36d50d591124109a48abb7480977ccb0"
"47b4d4f1ce7b0805df2d4fa3fe425f49b78535a11f4b87a4eba0638b3340c23d4e6b2"
"1ecebe9d5364ea6ead2d47b27836019e6ecb407000a50dc95a8614c9d0031a6e3a524"
- "d2345cfb76e15c1f69d5ba35bdfb6ec63bcb115a757ef79d9", 16),
+ "d2345cfb76e15c1f69d5ba35bdfb6ec63bcb115a757ef79d9",
+ 16,
+ ),
dmp1=int(
"18537e81006a68ea76d590cc88e73bd26bc38d09c977959748e5265c0ce21c0b5fd26"
- "53d975f97ef759b809f791487a8fff1264bf561627fb4527a3f0bbb72c85", 16),
+ "53d975f97ef759b809f791487a8fff1264bf561627fb4527a3f0bbb72c85",
+ 16,
+ ),
dmq1=int(
"c807eac5a1f1e1239f04b04dd16eff9a00565127a91046fa89e1eb5d6301cace85447"
- "4d1f47b0332bd35b4214b66e9166953241538f761f30d969272ee214f17", 16),
+ "4d1f47b0332bd35b4214b66e9166953241538f761f30d969272ee214f17",
+ 16,
+ ),
iqmp=int(
"133aa74dd41fe70fa244f07d0c4091a22f8c8f0134fe6aea9ec8b55383b758fefe358"
- "2beec36eca91715eee7d21931f24fa9e97e8e3a50f9cd0f731574a5eafcc", 16),
+ "2beec36eca91715eee7d21931f24fa9e97e8e3a50f9cd0f731574a5eafcc",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -245,31 +321,44 @@ RSA_KEY_1025 = RSAPrivateNumbers(
"bf276fe3523f38f5ddaf3ea9aa88486a9d8760ff732489075862bee0e599de5c5"
"f509b4519f4f446521bad15cd279a498fe1e89107ce0d237e3103d7c5eb801666"
"42e2924b152aebff97b71fdd2d68ebb45034cc784e2e822ff6d1edf98af3f3",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_1026 = RSAPrivateNumbers(
p=int(
"1fcbfb8719c5bdb5fe3eb0937c76bb096e750b9442dfe31d6a877a13aed2a6a4e9f79"
- "40f815f1c307dd6bc2b4b207bb6fe5be3a15bd2875a957492ce197cdedb1", 16),
+ "40f815f1c307dd6bc2b4b207bb6fe5be3a15bd2875a957492ce197cdedb1",
+ 16,
+ ),
q=int(
"1f704a0f6b8966dd52582fdc08227dd3dbaeaa781918b41144b692711091b4ca4eb62"
- "985c3513853828ce8739001dfba9a9a7f1a23cbcaf74280be925e2e7b50d", 16),
+ "985c3513853828ce8739001dfba9a9a7f1a23cbcaf74280be925e2e7b50d",
+ 16,
+ ),
d=int(
"c67975e35a1d0d0b3ebfca736262cf91990cb31cf4ac473c0c816f3bc2720bcba2475"
"e8d0de8535d257816c0fc53afc1b597eada8b229069d6ef2792fc23f59ffb4dc6c3d9"
"0a3c462082025a4cba7561296dd3d8870c4440d779406f00879afe2c681e7f5ee055e"
- "ff829e6e55883ec20830c72300762e6e3a333d94b4dbe4501", 16),
+ "ff829e6e55883ec20830c72300762e6e3a333d94b4dbe4501",
+ 16,
+ ),
dmp1=int(
"314730ca7066c55d086a9fbdf3670ef7cef816b9efea8b514b882ae9d647217cf41d7"
- "e9989269dc9893d02e315cb81f058c49043c2cac47adea58bdf5e20e841", 16),
+ "e9989269dc9893d02e315cb81f058c49043c2cac47adea58bdf5e20e841",
+ 16,
+ ),
dmq1=int(
"1da28a9d687ff7cfeebc2439240de7505a8796376968c8ec723a2b669af8ce53d9c88"
- "af18540bd78b2da429014923fa435f22697ac60812d7ca9c17a557f394cd", 16),
+ "af18540bd78b2da429014923fa435f22697ac60812d7ca9c17a557f394cd",
+ 16,
+ ),
iqmp=int(
"727947b57b8a36acd85180522f1b381bce5fdbd962743b3b14af98a36771a80f58ddd"
- "62675d72a5935190da9ddc6fd6d6d5e9e9f805a2e92ab8d56b820493cdf", 16),
+ "62675d72a5935190da9ddc6fd6d6d5e9e9f805a2e92ab8d56b820493cdf",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -277,31 +366,44 @@ RSA_KEY_1026 = RSAPrivateNumbers(
"9cfae6ab0446da18e26f33e1d753bc1cc03585c100cf0ab5ef056695706fc8b0c"
"9c710cd73fe6e5beda70f515a96fabd3cc5ac49efcb2594b220ff3b603fcd927f"
"6a0838ef04bf52f3ed9eab801f09e5aed1613ddeb946ed0fbb02060b3a36fd",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_1027 = RSAPrivateNumbers(
p=int(
"30135e54cfb072c3d3eaf2000f3ed92ceafc85efc867b9d4bf5612f2978c432040093"
- "4829f741c0f002b54af2a4433ff872b6321ef00ff1e72cba4e0ced937c7d", 16),
+ "4829f741c0f002b54af2a4433ff872b6321ef00ff1e72cba4e0ced937c7d",
+ 16,
+ ),
q=int(
"1d01a8aead6f86b78c875f18edd74214e06535d65da054aeb8e1851d6f3319b4fb6d8"
- "6b01e07d19f8261a1ded7dc08116345509ab9790e3f13e65c037e5bb7e27", 16),
+ "6b01e07d19f8261a1ded7dc08116345509ab9790e3f13e65c037e5bb7e27",
+ 16,
+ ),
d=int(
"21cf4477df79561c7818731da9b9c88cd793f1b4b8e175bd0bfb9c0941a4dc648ecf1"
"6d96b35166c9ea116f4c2eb33ce1c231e641a37c25e54c17027bdec08ddafcb83642e"
"795a0dd133155ccc5eed03b6e745930d9ac7cfe91f9045149f33295af03a2198c660f"
- "08d8150d13ce0e2eb02f21ac75d63b55822f77bd5be8d07619", 16),
+ "08d8150d13ce0e2eb02f21ac75d63b55822f77bd5be8d07619",
+ 16,
+ ),
dmp1=int(
"173fb695931e845179511c18b546b265cb79b517c135902377281bdf9f34205e1f399"
- "4603ad63e9f6e7885ea73a929f03fa0d6bed943051ce76cddde2d89d434d", 16),
+ "4603ad63e9f6e7885ea73a929f03fa0d6bed943051ce76cddde2d89d434d",
+ 16,
+ ),
dmq1=int(
"10956b387b2621327da0c3c8ffea2af8be967ee25163222746c28115a406e632a7f12"
- "5a9397224f1fa5c116cd3a313e5c508d31db2deb83b6e082d213e33f7fcf", 16),
+ "5a9397224f1fa5c116cd3a313e5c508d31db2deb83b6e082d213e33f7fcf",
+ 16,
+ ),
iqmp=int(
"234f833949f2c0d797bc6a0e906331e17394fa8fbc8449395766d3a8d222cf6167c48"
- "8e7fe1fe9721d3e3b699a595c8e6f063d92bd840dbc84d763b2b37002109", 16),
+ "8e7fe1fe9721d3e3b699a595c8e6f063d92bd840dbc84d763b2b37002109",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -309,31 +411,44 @@ RSA_KEY_1027 = RSAPrivateNumbers(
"0a5ae9f579ef1fd7e42937f921eb3123c4a045cc47a2159fbbf904783e654954c"
"42294c30a95c15db7c7b91f136244e548f62474b137087346c5522e54f226f49d"
"6c93bc58cb39972e41bde452bb3ae9d60eb93e5e1ce91d222138d9890c7d0b",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_1028 = RSAPrivateNumbers(
p=int(
"359d17378fae8e9160097daee78a206bd52efe1b757c12a6da8026cc4fc4bb2620f12"
- "b8254f4db6aed8228be8ee3e5a27ec7d31048602f01edb00befd209e8c75", 16),
+ "b8254f4db6aed8228be8ee3e5a27ec7d31048602f01edb00befd209e8c75",
+ 16,
+ ),
q=int(
"33a2e70b93d397c46e63b273dcd3dcfa64291342a6ce896e1ec8f1c0edc44106550f3"
- "c06e7d3ca6ea29eccf3f6ab5ac6235c265313d6ea8e8767e6a343f616581", 16),
+ "c06e7d3ca6ea29eccf3f6ab5ac6235c265313d6ea8e8767e6a343f616581",
+ 16,
+ ),
d=int(
"880640088d331aa5c0f4cf2887809a420a2bc086e671e6ffe4e47a8c80792c038a314"
"9a8e45ef9a72816ab45b36e3af6800351067a6b2751843d4232413146bb575491463a"
"8addd06ce3d1bcf7028ec6c5d938c545a20f0a40214b5c574ca7e840062b2b5f8ed49"
- "4b144bb2113677c4b10519177fee1d4f5fb8a1c159b0b47c01", 16),
+ "4b144bb2113677c4b10519177fee1d4f5fb8a1c159b0b47c01",
+ 16,
+ ),
dmp1=int(
"75f8c52dad2c1cea26b8bba63236ee4059489e3d2db766136098bcc6b67fde8f77cd3"
- "640035107bfb1ffc6480983cfb84fe0c3be008424ebc968a7db7e01f005", 16),
+ "640035107bfb1ffc6480983cfb84fe0c3be008424ebc968a7db7e01f005",
+ 16,
+ ),
dmq1=int(
"3893c59469e4ede5cd0e6ff9837ca023ba9b46ff40c60ccf1bec10f7d38db5b1ba817"
- "6c41a3f750ec4203b711455aca06d1e0adffc5cffa42bb92c7cb77a6c01", 16),
+ "6c41a3f750ec4203b711455aca06d1e0adffc5cffa42bb92c7cb77a6c01",
+ 16,
+ ),
iqmp=int(
"ad32aafae3c962ac25459856dc8ef1f733c3df697eced29773677f435d186cf759d1a"
- "5563dd421ec47b4d7e7f12f29647c615166d9c43fc49001b29089344f65", 16),
+ "5563dd421ec47b4d7e7f12f29647c615166d9c43fc49001b29089344f65",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -341,31 +456,44 @@ RSA_KEY_1028 = RSAPrivateNumbers(
"e3510c68073954d3ba4deb38643e7a820a4cf06e75f7f82eca545d412bd637819"
"45c28d406e95a6cced5ae924a8bfa4f3def3e0250d91246c269ec40c89c93a85a"
"cd3770ba4d2e774732f43abe94394de43fb57f93ca25f7a59d75d400a3eff5",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_1029 = RSAPrivateNumbers(
p=int(
"66f33e513c0b6b6adbf041d037d9b1f0ebf8de52812a3ac397a963d3f71ba64b3ad04"
- "e4d4b5e377e6fa22febcac292c907dc8dcfe64c807fd9a7e3a698850d983", 16),
+ "e4d4b5e377e6fa22febcac292c907dc8dcfe64c807fd9a7e3a698850d983",
+ 16,
+ ),
q=int(
"3b47a89a19022461dcc2d3c05b501ee76955e8ce3cf821beb4afa85a21a26fd7203db"
- "deb8941f1c60ada39fd6799f6c07eb8554113f1020460ec40e93cd5f6b21", 16),
+ "deb8941f1c60ada39fd6799f6c07eb8554113f1020460ec40e93cd5f6b21",
+ 16,
+ ),
d=int(
"280c42af8b1c719821f2f6e2bf5f3dd53c81b1f3e1e7cc4fce6e2f830132da0665bde"
"bc1e307106b112b52ad5754867dddd028116cf4471bc14a58696b99524b1ad8f05b31"
"cf47256e54ab4399b6a073b2c0452441438dfddf47f3334c13c5ec86ece4d33409056"
- "139328fafa992fb5f5156f25f9b21d3e1c37f156d963d97e41", 16),
+ "139328fafa992fb5f5156f25f9b21d3e1c37f156d963d97e41",
+ 16,
+ ),
dmp1=int(
"198c7402a4ec10944c50ab8488d7b5991c767e75eb2817bd427dff10335ae141fa2e8"
- "7c016dc22d975cac229b9ffdf7d943ddfd3a04b8bf82e83c3b32c5698b11", 16),
+ "7c016dc22d975cac229b9ffdf7d943ddfd3a04b8bf82e83c3b32c5698b11",
+ 16,
+ ),
dmq1=int(
"15fd30c7687b68ef7c2a30cdeb913ec56c4757c218cf9a04d995470797ee5f3a17558"
- "fbb6d00af245d2631d893b382da48a72bc8a613024289895952ab245b0c1", 16),
+ "fbb6d00af245d2631d893b382da48a72bc8a613024289895952ab245b0c1",
+ 16,
+ ),
iqmp=int(
"4f8fde17e84557a3f4e242d889e898545ab55a1a8e075c9bb0220173ccffe84659abe"
- "a235104f82e32750309389d4a52af57dbb6e48d831917b6efeb190176570", 16),
+ "a235104f82e32750309389d4a52af57dbb6e48d831917b6efeb190176570",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -373,31 +501,44 @@ RSA_KEY_1029 = RSAPrivateNumbers(
"99a9f74981c3eeaaf947d5c2d64a1a80f5c5108a49a715c3f7be95a016b8d3300"
"965ead4a4df76e642d761526803e9434d4ec61b10cb50526d4dcaef02593085de"
"d8c331c1b27b200a45628403065efcb2c0a0ca1f75d648d40a007fbfbf2cae3",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_1030 = RSAPrivateNumbers(
p=int(
"6f4ac8a8172ef1154cf7f80b5e91de723c35a4c512860bfdbafcc3b994a2384bf7796"
- "3a2dd0480c7e04d5d418629651a0de8979add6f47b23da14c27a682b69c9", 16),
+ "3a2dd0480c7e04d5d418629651a0de8979add6f47b23da14c27a682b69c9",
+ 16,
+ ),
q=int(
"65a9f83e07dea5b633e036a9dccfb32c46bf53c81040a19c574c3680838fc6d28bde9"
- "55c0ff18b30481d4ab52a9f5e9f835459b1348bbb563ad90b15a682fadb3", 16),
+ "55c0ff18b30481d4ab52a9f5e9f835459b1348bbb563ad90b15a682fadb3",
+ 16,
+ ),
d=int(
"290db707b3e1a96445ae8ea93af55a9f211a54ebe52995c2eb28085d1e3f09c986e73"
"a00010c8e4785786eaaa5c85b98444bd93b585d0c24363ccc22c482e150a3fd900176"
"86968e4fa20423ae72823b0049defceccb39bb34aa4ef64e6b14463b76d6a871c859e"
- "37285455b94b8e1527d1525b1682ac6f7c8fd79d576c55318c1", 16),
+ "37285455b94b8e1527d1525b1682ac6f7c8fd79d576c55318c1",
+ 16,
+ ),
dmp1=int(
"23f7fa84010225dea98297032dac5d45745a2e07976605681acfe87e0920a8ab3caf5"
- "9d9602f3d63dc0584f75161fd8fff20c626c21c5e02a85282276a74628a9", 16),
+ "9d9602f3d63dc0584f75161fd8fff20c626c21c5e02a85282276a74628a9",
+ 16,
+ ),
dmq1=int(
"18ebb657765464a8aa44bf019a882b72a2110a77934c54915f70e6375088b10331982"
- "962bce1c7edd8ef9d3d95aa2566d2a99da6ebab890b95375919408d00f33", 16),
+ "962bce1c7edd8ef9d3d95aa2566d2a99da6ebab890b95375919408d00f33",
+ 16,
+ ),
iqmp=int(
"3d59d208743c74054151002d77dcdfc55af3d41357e89af88d7eef2767be54c290255"
- "9258d85cf2a1083c035a33e65a1ca46dc8b706847c1c6434cef7b71a9dae", 16),
+ "9258d85cf2a1083c035a33e65a1ca46dc8b706847c1c6434cef7b71a9dae",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -405,31 +546,44 @@ RSA_KEY_1030 = RSAPrivateNumbers(
"8fcdbb6b4e12168304f587999f9d96a421fc80cb933a490df85d25883e6a88750"
"d6bd8b3d4117251eee8f45e70e6daac7dbbd92a9103c623a09355cf00e3f16168"
"e38b9c4cb5b368deabbed8df466bc6835eaba959bc1c2f4ec32a09840becc8b",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_1031 = RSAPrivateNumbers(
p=int(
"c0958c08e50137db989fb7cc93abf1984543e2f955d4f43fb2967f40105e79274c852"
- "293fa06ce63ca8436155e475ed6d1f73fea4c8e2516cc79153e3dc83e897", 16),
+ "293fa06ce63ca8436155e475ed6d1f73fea4c8e2516cc79153e3dc83e897",
+ 16,
+ ),
q=int(
"78cae354ea5d6862e5d71d20273b7cddb8cdfab25478fe865180676b04250685c4d03"
- "30c216574f7876a7b12dfe69f1661d3b0cea6c2c0dcfb84050f817afc28d", 16),
+ "30c216574f7876a7b12dfe69f1661d3b0cea6c2c0dcfb84050f817afc28d",
+ 16,
+ ),
d=int(
"1d55cc02b17a5d25bfb39f2bc58389004d0d7255051507f75ef347cdf5519d1a00f4b"
"d235ce4171bfab7bdb7a6dcfae1cf41433fb7da5923cc84f15a675c0b83492c95dd99"
"a9fc157aea352ffdcbb5d59dbc3662171d5838d69f130678ee27841a79ef64f679ce9"
- "3821fa69c03f502244c04b737edad8967def8022a144feaab29", 16),
+ "3821fa69c03f502244c04b737edad8967def8022a144feaab29",
+ 16,
+ ),
dmp1=int(
"5b1c2504ec3a984f86b4414342b5bcf59a0754f13adf25b2a0edbc43f5ba8c3cc061d"
- "80b03e5866d059968f0d10a98deaeb4f7830436d76b22cf41f2914e13eff", 16),
+ "80b03e5866d059968f0d10a98deaeb4f7830436d76b22cf41f2914e13eff",
+ 16,
+ ),
dmq1=int(
"6c361e1819691ab5d67fb2a8f65c958d301cdf24d90617c68ec7005edfb4a7b638cde"
- "79d4b61cfba5c86e8c0ccf296bc7f611cb8d4ae0e072a0f68552ec2d5995", 16),
+ "79d4b61cfba5c86e8c0ccf296bc7f611cb8d4ae0e072a0f68552ec2d5995",
+ 16,
+ ),
iqmp=int(
"b7d61945fdc8b92e075b15554bab507fa8a18edd0a18da373ec6c766c71eece61136a"
- "84b90b6d01741d40458bfad17a9bee9d4a8ed2f6e270782dc3bf5d58b56e", 16),
+ "84b90b6d01741d40458bfad17a9bee9d4a8ed2f6e270782dc3bf5d58b56e",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -437,38 +591,51 @@ RSA_KEY_1031 = RSAPrivateNumbers(
"9f73da0690581691626d8a7cf5d972cced9c2091ccf999024b23b4e6dc6d99f80"
"a454737dec0caffaebe4a3fac250ed02079267c8f39620b5ae3e125ca35338522"
"dc9353ecac19cb2fe3b9e3a9291619dbb1ea3a7c388e9ee6469fbf5fb22892b",
- 16),
- )
+ 16,
+ ),
+ ),
)
RSA_KEY_1536 = RSAPrivateNumbers(
p=int(
"f1a65fa4e2aa6e7e2b560251e8a4cd65b625ad9f04f6571785782d1c213d91c961637"
"0c572f2783caf2899f7fb690cf99a0184257fbd4b071b212c88fb348279a5387e61f1"
- "17e9c62980c45ea863fa9292087c0f66ecdcde6443d5a37268bf71", 16),
+ "17e9c62980c45ea863fa9292087c0f66ecdcde6443d5a37268bf71",
+ 16,
+ ),
q=int(
"e54c2cbc3839b1da6ae6fea45038d986d6f523a3ae76051ba20583aab711ea5965cf5"
"3cf54128cc9573f7460bba0fd6758a57aaf240c391790fb38ab473d83ef735510c53d"
- "1d10c31782e8fd7da42615e33565745c30a5e6ceb2a3ae0666cc35", 16),
+ "1d10c31782e8fd7da42615e33565745c30a5e6ceb2a3ae0666cc35",
+ 16,
+ ),
d=int(
"7bcad87e23da2cb2a8c328883fabce06e1f8e9b776c8bf253ad9884e6200e3bd9bd3b"
"a2cbe87d3854527bf005ba5d878c5b0fa20cfb0a2a42884ae95ca12bf7304285e9214"
"5e992f7006c7c0ae839ad550da495b143bec0f4806c7f44caed45f3ccc6dc44cfaf30"
"7abdb757e3d28e41c2d21366835c0a41e50a95af490ac03af061d2feb36ac0afb87be"
"a13fb0f0c5a410727ebedb286c77f9469473fae27ef2c836da6071ef7efc1647f1233"
- "4009a89eecb09a8287abc8c2afd1ddd9a1b0641", 16),
+ "4009a89eecb09a8287abc8c2afd1ddd9a1b0641",
+ 16,
+ ),
dmp1=int(
"a845366cd6f9df1f34861bef7594ed025aa83a12759e245f58adaa9bdff9c3befb760"
"75d3701e90038e888eec9bf092df63400152cb25fc07effc6c74c45f0654ccbde15cd"
- "90dd5504298a946fa5cf22a956072da27a6602e6c6e5c97f2db9c1", 16),
+ "90dd5504298a946fa5cf22a956072da27a6602e6c6e5c97f2db9c1",
+ 16,
+ ),
dmq1=int(
"28b0c1e78cdac03310717992d321a3888830ec6829978c048156152d805b4f8919c61"
"70b5dd204e5ddf3c6c53bc6aff15d0bd09faff7f351b94abb9db980b31f150a6d7573"
- "08eb66938f89a5225cb4dd817a824c89e7a0293b58fc2eefb7e259", 16),
+ "08eb66938f89a5225cb4dd817a824c89e7a0293b58fc2eefb7e259",
+ 16,
+ ),
iqmp=int(
"6c1536c0e16e42a094b6caaf50231ba81916871497d73dcbbbd4bdeb9e60cae0413b3"
"8143b5d680275b29ed7769fe5577e4f9b3647ddb064941120914526d64d80016d2eb7"
- "dc362da7c569623157f3d7cff8347f11494bf5c048d77e28d3f515", 16),
+ "dc362da7c569623157f3d7cff8347f11494bf5c048d77e28d3f515",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -477,8 +644,10 @@ RSA_KEY_1536 = RSAPrivateNumbers(
"c248ceef4050160705c188043c8559bf6dbfb6c4bb382eda4e9547575a8227d5b"
"3c0a7088391364cf9f018d8bea053b226ec65e8cdbeaf48a071d0074860a734b1"
"cb7d2146d43014b20776dea42f7853a54690e6cbbf3331a9f43763cfe2a51c329"
- "3bea3b2eebec0d8e43eb317a443afe541107d886e5243c096091543ae65", 16),
- )
+ "3bea3b2eebec0d8e43eb317a443afe541107d886e5243c096091543ae65",
+ 16,
+ ),
+ ),
)
RSA_KEY_2048 = RSAPrivateNumbers(
@@ -486,12 +655,16 @@ RSA_KEY_2048 = RSAPrivateNumbers(
"e14202e58c5f7446648d75e5dc465781f661f6b73000c080368afcfb21377f4ef19da"
"845d4ef9bc6b151f6d9f34629103f2e57615f9ba0a3a2fbb035069e1d63b4bb0e78ad"
"dad1ec3c6f87e25c877a1c4c1972098e09158ef7b9bc163852a18d44a70b7b31a03dc"
- "2614fd9ab7bf002cba79054544af3bfbdb6aed06c7b24e6ab", 16),
+ "2614fd9ab7bf002cba79054544af3bfbdb6aed06c7b24e6ab",
+ 16,
+ ),
q=int(
"dbe2bea1ff92599bd19f9d045d6ce62250c05cfeac5117f3cf3e626cb696e3d886379"
"557d5a57b7476f9cf886accfd40508a805fe3b45a78e1a8a125e516cda91640ee6398"
"ec5a39d3e6b177ef12ab00d07907a17640e4ca454fd8487da3c4ffa0d5c2a5edb1221"
- "1c8e33c7ee9fa6753771fd111ec04b8317f86693eb2928c89", 16),
+ "1c8e33c7ee9fa6753771fd111ec04b8317f86693eb2928c89",
+ 16,
+ ),
d=int(
"aef17f80f2653bc30539f26dd4c82ed6abc1d1b53bc0abcdbee47e9a8ab433abde865"
"9fcfae1244d22de6ad333c95aee7d47f30b6815065ac3322744d3ea75058002cd1b29"
@@ -500,22 +673,30 @@ RSA_KEY_2048 = RSAPrivateNumbers(
"c8263ce2802a769a090e993fd49abc50c3d3c78c29bee2de0c98055d2f102f1c5684b"
"8dddee611d5205392d8e8dd61a15bf44680972a87f040a611a149271eeb2573f8bf6f"
"627dfa70e77def2ee6584914fa0290e041349ea0999cdff3e493365885b906cbcf195"
- "843345809a85098cca90fea014a21", 16),
+ "843345809a85098cca90fea014a21",
+ 16,
+ ),
dmp1=int(
"9ba56522ffcfa5244eae805c87cc0303461f82be29691b9a7c15a5a050df6c143c575"
"7c288d3d7ab7f32c782e9d9fcddc10a604e6425c0e5d0e46069035d95a923646d276d"
"d9d95b8696fa29ab0de18e53f6f119310f8dd9efca62f0679291166fed8cbd5f18fe1"
- "3a5f1ead1d71d8c90f40382818c18c8d069be793dbc094f69", 16),
+ "3a5f1ead1d71d8c90f40382818c18c8d069be793dbc094f69",
+ 16,
+ ),
dmq1=int(
"a8d4a0aaa2212ccc875796a81353da1fdf00d46676c88d2b96a4bfcdd924622d8e607"
"f3ac1c01dda7ebfb0a97dd7875c2a7b2db6728fb827b89c519f5716fb3228f4121647"
"04b30253c17de2289e9cce3343baa82eb404f789e094a094577a9b0c5314f1725fdf5"
- "8e87611ad20da331bd30b8aebc7dc97d0e9a9ba8579772c9", 16),
+ "8e87611ad20da331bd30b8aebc7dc97d0e9a9ba8579772c9",
+ 16,
+ ),
iqmp=int(
"17bd5ef638c49440d1853acb3fa63a5aca28cb7f94ed350db7001c8445da8943866a7"
"0936e1ee2716c98b484e357cc054d82fbbd98d42f880695d38a1dd4eb096f629b9417"
"aca47e6de5da9f34e60e8a0ffd7e35be74deeef67298d94b3e0db73fc4b7a4cb360c8"
- "9d2117a0bfd9434d37dc7c027d6b01e5295c875015510917d", 16),
+ "9d2117a0bfd9434d37dc7c027d6b01e5295c875015510917d",
+ 16,
+ ),
public_numbers=RSAPublicNumbers(
e=65537,
n=int(
@@ -526,8 +707,10 @@ RSA_KEY_2048 = RSAPrivateNumbers(
"c29e53635e24c87a5b2c4215968063cdeb68a972babbc1e3cff00fb9a80e372a4"
"d0c2c920d1e8cee333ce470dc2e8145adb05bf29aee1d24f141e8cc784989c587"
"fc6fbacd979f3f2163c1d7299b365bc72ffe2848e967aed1e48dcc515b3a50ed4"
- "de04fd053846ca10a223b10cc841cc80fdebee44f3114c13e886af583", 16),
- )
+ "de04fd053846ca10a223b10cc841cc80fdebee44f3114c13e886af583",
+ 16,
+ ),
+ ),
)
RSA_KEY_2048_ALT = RSAPrivateNumbers(
@@ -598,6 +781,36 @@ RSA_KEY_2048_ALT = RSAPrivateNumbers(
"715070507278514207864914944621214574162116786377990456375"
"964817771730371110612100247262908550409785456157505694419"
"00451152778245269283276012328748538414051025541"
- )
- )
+ ),
+ ),
)
+
+RSA_KEY_CORRUPTED = b"""
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAuYE4k09MAsi1yjMrXekMe6sT9bEt3ko47dnmN8YBgO8DiiCc
+226TnQPvuX3FGxU+Y1zTJpcvVL3L37UOvh4CSb9zKyrFK9/x/UcCfK3Eq8JdS98P
+CVeGpkp5E+vwIKY72rc1RSSSCs0PtFdYbSn4trwf5BjPxIqXwIOS3R7zC7cLPHY4
+YdsM4gLGVOP17uXJr/MPoAtWTBVm5zx4bHm6Xclzgf86sbPdL3LxNs0fz4HqJZgA
+6EUtyl6Qypq2LjXbdmm2i3vC+MxW6nEPItPqgComhq0zBmVonsiEO87rEtD548Yq
+DKvxwHhlcODcVkAYebJ+W5L6PPJBNYA3t5wYyQIDAQABAoIBAAbHkg5msftpGt5Z
+Vb3yUuepem7hWTF5YFlIRw5l2wNcURNpbswEhOVNJbuG+KCple7Dw4TuDmhHs/zr
+BRqpDhXldhrUtb2uc3ihqWiVFJbieqE4jUbGvMJusvtXXeDwU6wGWzV/V4qndCrk
+u4PGypk4Cbbq6ZP2oufPryQ3D4Ff1TA06RSWdP3Cg673VqwLtkXwsRDhymAviiqU
+hxQg8bRNiD7mYoUKyLVeV7YRDLTBugfiFmy54yC99NJclLkYmzCgRt1EuoW0Hixx
+EIQFEOLftgpc+sKpbbiOileMsc/stytHXXqfgozhBxDNeSzdNYfwEpkLJpLZSUNV
+EhS4X1cCgYEAz+7DkXksWw9zLqYniMIcvcBnHQcy3Anqbcu8Zbw+I9wOwzNt44Bo
+f88i2idvWvMsRq/LX4WD4jjPB4Z3wAzGBCq+2cy0GrWByMu+VbpwCrntRBkS5huY
+IIf1nr1+BuySNt8TL6nZNKz0D8+5c8wT+VbVdPH//4MzfDrK81PPnesCgYEA5GMy
+ji4l+8zO33LFMlWQGYgfSMd4jGMQD0VCvfhlosK0Py0AfZj/GKEGHduo/37KVVvb
+6XdJqYgB7OxPmdEqbMGeYPKv7pKkG1jXRuEtmXXJ9hS1t0oIvXJLHJnQrOOoRRAR
++xJZbI7WjemY+ZCMOAPT1tm97pxjs81WgSJ6ExsCgYEAze5ADfEeNskkYAz6lnz4
+jgzhkmQwwK+pVzgxy9g8brNkg3qJ2Iix9fKlJ71qkX7IWPF9z4qhxQhSMbfBHZkI
++9OB1J7huJoOgVkXliwIbvcYvxq+Fts5XO6KGb699AmT/XgMvmXO0lbAGLC3kLGL
+DqQrH3kU+m9sLBrmKPrWYiUCgYEA3/8etW4zmMvd1jAFkoFyzGfCbyocZGxAcwm2
+FQYMAN8/03p6sbSd9XTwv9YR4Uxke+WURkjVuW2IneuDgtQv6QCFKob74Jx4Uc4H
+jiAKDioFg9H6C6OUAOKZIpsFnJvIDLxfNkVf6WYKrrL+cz6/F61BVsbGTsGZ094/
+ynWbDyMCgYEAh44C/wkebe0zz/llG+KTRGENsw1c7+pm0/l3wPYAlH02ewbyRjFf
+OKPfyyBtBkoD5rG3IbLyPxsbd3wWwyUzSYq02qRJq43XqyMZhRnNlYhEnNu/Gr5H
+sN1f13zqkKoRxxbIjyh4RDYlAv4Sehk27z2Q3gBe9bI5xKkoQ/VfF2w=
+-----END RSA PRIVATE KEY-----
+"""
diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py
index f281ba288..d14dcad9f 100644
--- a/tests/hazmat/primitives/test_3des.py
+++ b/tests/hazmat/primitives/test_3des.py
@@ -28,7 +28,7 @@ from ...utils import load_nist_vectors
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestTripleDESModeCBC(object):
- test_KAT = generate_encrypt_test(
+ test_kat = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "CBC"),
[
@@ -42,14 +42,10 @@ class TestTripleDESModeCBC(object):
lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)),
)
- test_MMT = generate_encrypt_test(
+ test_mmt = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "CBC"),
- [
- "TCBCMMT1.rsp",
- "TCBCMMT2.rsp",
- "TCBCMMT3.rsp",
- ],
+ ["TCBCMMT1.rsp", "TCBCMMT2.rsp", "TCBCMMT3.rsp"],
lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
binascii.unhexlify(key1 + key2 + key3)
),
@@ -65,7 +61,7 @@ class TestTripleDESModeCBC(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestTripleDESModeOFB(object):
- test_KAT = generate_encrypt_test(
+ test_kat = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "OFB"),
[
@@ -79,14 +75,10 @@ class TestTripleDESModeOFB(object):
lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv)),
)
- test_MMT = generate_encrypt_test(
+ test_mmt = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "OFB"),
- [
- "TOFBMMT1.rsp",
- "TOFBMMT2.rsp",
- "TOFBMMT3.rsp",
- ],
+ ["TOFBMMT1.rsp", "TOFBMMT2.rsp", "TOFBMMT3.rsp"],
lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
binascii.unhexlify(key1 + key2 + key3)
),
@@ -102,7 +94,7 @@ class TestTripleDESModeOFB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestTripleDESModeCFB(object):
- test_KAT = generate_encrypt_test(
+ test_kat = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "CFB"),
[
@@ -116,14 +108,10 @@ class TestTripleDESModeCFB(object):
lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)),
)
- test_MMT = generate_encrypt_test(
+ test_mmt = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "CFB"),
- [
- "TCFB64MMT1.rsp",
- "TCFB64MMT2.rsp",
- "TCFB64MMT3.rsp",
- ],
+ ["TCFB64MMT1.rsp", "TCFB64MMT2.rsp", "TCFB64MMT3.rsp"],
lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
binascii.unhexlify(key1 + key2 + key3)
),
@@ -139,7 +127,7 @@ class TestTripleDESModeCFB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestTripleDESModeCFB8(object):
- test_KAT = generate_encrypt_test(
+ test_kat = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "CFB"),
[
@@ -153,14 +141,10 @@ class TestTripleDESModeCFB8(object):
lambda iv, **kwargs: modes.CFB8(binascii.unhexlify(iv)),
)
- test_MMT = generate_encrypt_test(
+ test_mmt = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "CFB"),
- [
- "TCFB8MMT1.rsp",
- "TCFB8MMT2.rsp",
- "TCFB8MMT3.rsp",
- ],
+ ["TCFB8MMT1.rsp", "TCFB8MMT2.rsp", "TCFB8MMT3.rsp"],
lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
binascii.unhexlify(key1 + key2 + key3)
),
@@ -176,7 +160,7 @@ class TestTripleDESModeCFB8(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestTripleDESModeECB(object):
- test_KAT = generate_encrypt_test(
+ test_kat = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "ECB"),
[
@@ -190,14 +174,10 @@ class TestTripleDESModeECB(object):
lambda **kwargs: modes.ECB(),
)
- test_MMT = generate_encrypt_test(
+ test_mmt = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "3DES", "ECB"),
- [
- "TECBMMT1.rsp",
- "TECBMMT2.rsp",
- "TECBMMT3.rsp",
- ],
+ ["TECBMMT1.rsp", "TECBMMT2.rsp", "TECBMMT3.rsp"],
lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
binascii.unhexlify(key1 + key2 + key3)
),
diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py
index e1a17a974..270693182 100644
--- a/tests/hazmat/primitives/test_aead.py
+++ b/tests/hazmat/primitives/test_aead.py
@@ -12,13 +12,17 @@ import pytest
from cryptography.exceptions import InvalidTag, UnsupportedAlgorithm, _Reasons
from cryptography.hazmat.backends.interfaces import CipherBackend
from cryptography.hazmat.primitives.ciphers.aead import (
- AESCCM, AESGCM, ChaCha20Poly1305
+ AESCCM,
+ AESGCM,
+ ChaCha20Poly1305,
)
from .utils import _load_all_params
from ...utils import (
- load_nist_ccm_vectors, load_nist_vectors, load_vectors_from_file,
- raises_unsupported_algorithm
+ load_nist_ccm_vectors,
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
@@ -37,7 +41,7 @@ def _aead_supported(cls):
@pytest.mark.skipif(
_aead_supported(ChaCha20Poly1305),
- reason="Requires OpenSSL without ChaCha20Poly1305 support"
+ reason="Requires OpenSSL without ChaCha20Poly1305 support",
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
def test_chacha20poly1305_unsupported_on_older_openssl(backend):
@@ -47,7 +51,7 @@ def test_chacha20poly1305_unsupported_on_older_openssl(backend):
@pytest.mark.skipif(
not _aead_supported(ChaCha20Poly1305),
- reason="Does not support ChaCha20Poly1305"
+ reason="Does not support ChaCha20Poly1305",
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestChaCha20Poly1305(object):
@@ -78,11 +82,12 @@ class TestChaCha20Poly1305(object):
[
[object(), b"data", b""],
[b"0" * 12, object(), b""],
- [b"0" * 12, b"data", object()]
- ]
+ [b"0" * 12, b"data", object()],
+ ],
)
- def test_params_not_bytes_encrypt(self, nonce, data, associated_data,
- backend):
+ def test_params_not_bytes_encrypt(
+ self, nonce, data, associated_data, backend
+ ):
key = ChaCha20Poly1305.generate_key()
chacha = ChaCha20Poly1305(key)
with pytest.raises(TypeError):
@@ -121,8 +126,8 @@ class TestChaCha20Poly1305(object):
"vector",
load_vectors_from_file(
os.path.join("ciphers", "ChaCha20Poly1305", "openssl.txt"),
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_openssl_vectors(self, vector, backend):
key = binascii.unhexlify(vector["key"])
@@ -145,8 +150,8 @@ class TestChaCha20Poly1305(object):
"vector",
load_vectors_from_file(
os.path.join("ciphers", "ChaCha20Poly1305", "boringssl.txt"),
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_boringssl_vectors(self, vector, backend):
key = binascii.unhexlify(vector["key"])
@@ -183,20 +188,6 @@ class TestChaCha20Poly1305(object):
assert computed_pt2 == pt
-@pytest.mark.skipif(
- _aead_supported(AESCCM),
- reason="Requires OpenSSL without AES-CCM support"
-)
-@pytest.mark.requires_backend_interface(interface=CipherBackend)
-def test_aesccm_unsupported_on_older_openssl(backend):
- with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
- AESCCM(AESCCM.generate_key(128))
-
-
-@pytest.mark.skipif(
- not _aead_supported(AESCCM),
- reason="Does not support AESCCM"
-)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestAESCCM(object):
def test_data_too_large(self):
@@ -245,22 +236,30 @@ class TestAESCCM(object):
_load_all_params(
os.path.join("ciphers", "AES", "CCM"),
[
- "DVPT128.rsp", "DVPT192.rsp", "DVPT256.rsp",
- "VADT128.rsp", "VADT192.rsp", "VADT256.rsp",
- "VNT128.rsp", "VNT192.rsp", "VNT256.rsp",
- "VPT128.rsp", "VPT192.rsp", "VPT256.rsp",
+ "DVPT128.rsp",
+ "DVPT192.rsp",
+ "DVPT256.rsp",
+ "VADT128.rsp",
+ "VADT192.rsp",
+ "VADT256.rsp",
+ "VNT128.rsp",
+ "VNT192.rsp",
+ "VNT256.rsp",
+ "VPT128.rsp",
+ "VPT192.rsp",
+ "VPT256.rsp",
],
- load_nist_ccm_vectors
- )
+ load_nist_ccm_vectors,
+ ),
)
def test_vectors(self, vector, backend):
key = binascii.unhexlify(vector["key"])
nonce = binascii.unhexlify(vector["nonce"])
- adata = binascii.unhexlify(vector["adata"])[:vector["alen"]]
+ adata = binascii.unhexlify(vector["adata"])[: vector["alen"]]
ct = binascii.unhexlify(vector["ct"])
- pt = binascii.unhexlify(vector["payload"])[:vector["plen"]]
+ pt = binascii.unhexlify(vector["payload"])[: vector["plen"]]
aesccm = AESCCM(key, vector["tlen"])
- if vector.get('fail'):
+ if vector.get("fail"):
with pytest.raises(InvalidTag):
aesccm.decrypt(nonce, ct, adata)
else:
@@ -293,7 +292,7 @@ class TestAESCCM(object):
[object(), b"data", b""],
[b"0" * 12, object(), b""],
[b"0" * 12, b"data", object()],
- ]
+ ],
)
def test_params_not_bytes(self, nonce, data, associated_data, backend):
key = AESCCM.generate_key(128)
@@ -359,7 +358,7 @@ def _load_gcm_vectors():
"gcmEncryptExtIV192.rsp",
"gcmEncryptExtIV256.rsp",
],
- load_nist_vectors
+ load_nist_vectors,
)
return [x for x in vectors if len(x["tag"]) == 32]
@@ -378,9 +377,18 @@ class TestAESGCM(object):
aesgcm.encrypt(nonce, b"", FakeData())
@pytest.mark.parametrize("vector", _load_gcm_vectors())
- def test_vectors(self, vector):
- key = binascii.unhexlify(vector["key"])
+ def test_vectors(self, backend, vector):
nonce = binascii.unhexlify(vector["iv"])
+
+ if len(nonce) < 8:
+ pytest.skip("GCM does not support less than 64-bit IVs")
+
+ if backend._fips_enabled and len(nonce) != 12:
+ # Red Hat disables non-96-bit IV support as part of its FIPS
+ # patches.
+ pytest.skip("Non-96-bit IVs unsupported in FIPS mode.")
+
+ key = binascii.unhexlify(vector["key"])
aad = binascii.unhexlify(vector["aad"])
ct = binascii.unhexlify(vector["ct"])
pt = binascii.unhexlify(vector.get("pt", b""))
@@ -401,8 +409,8 @@ class TestAESGCM(object):
[
[object(), b"data", b""],
[b"0" * 12, object(), b""],
- [b"0" * 12, b"data", object()]
- ]
+ [b"0" * 12, b"data", object()],
+ ],
)
def test_params_not_bytes(self, nonce, data, associated_data, backend):
key = AESGCM.generate_key(128)
@@ -413,11 +421,17 @@ class TestAESGCM(object):
with pytest.raises(TypeError):
aesgcm.decrypt(nonce, data, associated_data)
- def test_invalid_nonce_length(self, backend):
+ @pytest.mark.parametrize("length", [7, 129])
+ def test_invalid_nonce_length(self, length, backend):
+ if backend._fips_enabled:
+ # Red Hat disables non-96-bit IV support as part of its FIPS
+ # patches.
+ pytest.skip("Non-96-bit IVs unsupported in FIPS mode.")
+
key = AESGCM.generate_key(128)
aesgcm = AESGCM(key)
with pytest.raises(ValueError):
- aesgcm.encrypt(b"", b"hi", None)
+ aesgcm.encrypt(b"\x00" * length, b"hi", None)
def test_bad_key(self, backend):
with pytest.raises(TypeError):
diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py
index 90a6b3b0a..f98ba6fdd 100644
--- a/tests/hazmat/primitives/test_aes.py
+++ b/tests/hazmat/primitives/test_aes.py
@@ -12,7 +12,8 @@ import pytest
from cryptography.hazmat.backends.interfaces import CipherBackend
from cryptography.hazmat.primitives.ciphers import algorithms, base, modes
-from .utils import _load_all_params, generate_aead_test, generate_encrypt_test
+from .utils import _load_all_params, generate_encrypt_test
+from ...doubles import DummyMode
from ...utils import load_nist_vectors
@@ -30,11 +31,15 @@ class TestAESModeXTS(object):
# data unit length that is divisible by 8. The NIST vectors include
# tests for implementations that support encryption of data that is
# not divisible modulo 8, but OpenSSL is not such an implementation.
- [x for x in _load_all_params(
- os.path.join("ciphers", "AES", "XTS", "tweak-128hexstr"),
- ["XTSGenAES128.rsp", "XTSGenAES256.rsp"],
- load_nist_vectors
- ) if int(x["dataunitlen"]) / 8.0 == int(x["dataunitlen"]) // 8]
+ [
+ x
+ for x in _load_all_params(
+ os.path.join("ciphers", "AES", "XTS", "tweak-128hexstr"),
+ ["XTSGenAES128.rsp", "XTSGenAES256.rsp"],
+ load_nist_vectors,
+ )
+ if int(x["dataunitlen"]) / 8.0 == int(x["dataunitlen"]) // 8
+ ],
)
def test_xts_vectors(self, vector, backend):
key = binascii.unhexlify(vector["key"])
@@ -58,7 +63,7 @@ class TestAESModeXTS(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestAESModeCBC(object):
- test_CBC = generate_encrypt_test(
+ test_cbc = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "AES", "CBC"),
[
@@ -91,7 +96,7 @@ class TestAESModeCBC(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestAESModeECB(object):
- test_ECB = generate_encrypt_test(
+ test_ecb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "AES", "ECB"),
[
@@ -124,7 +129,7 @@ class TestAESModeECB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestAESModeOFB(object):
- test_OFB = generate_encrypt_test(
+ test_ofb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "AES", "OFB"),
[
@@ -157,7 +162,7 @@ class TestAESModeOFB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestAESModeCFB(object):
- test_CFB = generate_encrypt_test(
+ test_cfb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "AES", "CFB"),
[
@@ -190,7 +195,7 @@ class TestAESModeCFB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestAESModeCFB8(object):
- test_CFB8 = generate_encrypt_test(
+ test_cfb8 = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "AES", "CFB"),
[
@@ -223,7 +228,7 @@ class TestAESModeCFB8(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestAESModeCTR(object):
- test_CTR = generate_encrypt_test(
+ test_ctr = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "AES", "CTR"),
["aes-128-ctr.txt", "aes-192-ctr.txt", "aes-256-ctr.txt"],
@@ -232,249 +237,6 @@ class TestAESModeCTR(object):
)
-@pytest.mark.supported(
- only_if=lambda backend: backend.cipher_supported(
- algorithms.AES(b"\x00" * 16), modes.GCM(b"\x00" * 12)
- ),
- skip_message="Does not support AES GCM",
-)
-@pytest.mark.requires_backend_interface(interface=CipherBackend)
-class TestAESModeGCM(object):
- test_GCM = generate_aead_test(
- load_nist_vectors,
- os.path.join("ciphers", "AES", "GCM"),
- [
- "gcmDecrypt128.rsp",
- "gcmDecrypt192.rsp",
- "gcmDecrypt256.rsp",
- "gcmEncryptExtIV128.rsp",
- "gcmEncryptExtIV192.rsp",
- "gcmEncryptExtIV256.rsp",
- ],
- algorithms.AES,
- modes.GCM,
- )
-
- def test_gcm_tag_with_only_aad(self, backend):
- key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
- iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
- aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
- tag = binascii.unhexlify(b"0f247e7f9c2505de374006738018493b")
-
- cipher = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv),
- backend=backend
- )
- encryptor = cipher.encryptor()
- encryptor.authenticate_additional_data(aad)
- encryptor.finalize()
- assert encryptor.tag == tag
-
- def test_gcm_ciphertext_with_no_aad(self, backend):
- key = binascii.unhexlify(b"e98b72a9881a84ca6b76e0f43e68647a")
- iv = binascii.unhexlify(b"8b23299fde174053f3d652ba")
- ct = binascii.unhexlify(b"5a3c1cf1985dbb8bed818036fdd5ab42")
- tag = binascii.unhexlify(b"23c7ab0f952b7091cd324835043b5eb5")
- pt = binascii.unhexlify(b"28286a321293253c3e0aa2704a278032")
-
- cipher = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv),
- backend=backend
- )
- encryptor = cipher.encryptor()
- computed_ct = encryptor.update(pt) + encryptor.finalize()
- assert computed_ct == ct
- assert encryptor.tag == tag
-
- def test_gcm_ciphertext_limit(self, backend):
- encryptor = base.Cipher(
- algorithms.AES(b"\x00" * 16),
- modes.GCM(b"\x01" * 16),
- backend=backend
- ).encryptor()
- encryptor._bytes_processed = modes.GCM._MAX_ENCRYPTED_BYTES - 16
- encryptor.update(b"0" * 16)
- assert (
- encryptor._bytes_processed == modes.GCM._MAX_ENCRYPTED_BYTES
- )
- with pytest.raises(ValueError):
- encryptor.update(b"0")
-
- def test_gcm_aad_limit(self, backend):
- encryptor = base.Cipher(
- algorithms.AES(b"\x00" * 16),
- modes.GCM(b"\x01" * 16),
- backend=backend
- ).encryptor()
- encryptor._aad_bytes_processed = modes.GCM._MAX_AAD_BYTES - 16
- encryptor.authenticate_additional_data(b"0" * 16)
- assert encryptor._aad_bytes_processed == modes.GCM._MAX_AAD_BYTES
- with pytest.raises(ValueError):
- encryptor.authenticate_additional_data(b"0")
-
- def test_gcm_ciphertext_increments(self, backend):
- encryptor = base.Cipher(
- algorithms.AES(b"\x00" * 16),
- modes.GCM(b"\x01" * 16),
- backend=backend
- ).encryptor()
- encryptor.update(b"0" * 8)
- assert encryptor._bytes_processed == 8
- encryptor.update(b"0" * 7)
- assert encryptor._bytes_processed == 15
- encryptor.update(b"0" * 18)
- assert encryptor._bytes_processed == 33
-
- def test_gcm_aad_increments(self, backend):
- encryptor = base.Cipher(
- algorithms.AES(b"\x00" * 16),
- modes.GCM(b"\x01" * 16),
- backend=backend
- ).encryptor()
- encryptor.authenticate_additional_data(b"0" * 8)
- assert encryptor._aad_bytes_processed == 8
- encryptor.authenticate_additional_data(b"0" * 18)
- assert encryptor._aad_bytes_processed == 26
-
- def test_gcm_tag_decrypt_none(self, backend):
- key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
- iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
- aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
-
- encryptor = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv),
- backend=backend
- ).encryptor()
- encryptor.authenticate_additional_data(aad)
- encryptor.finalize()
-
- if (
- backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
- not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
- ):
- with pytest.raises(NotImplementedError):
- decryptor = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv),
- backend=backend
- ).decryptor()
- else:
- decryptor = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv),
- backend=backend
- ).decryptor()
- decryptor.authenticate_additional_data(aad)
- with pytest.raises(ValueError):
- decryptor.finalize()
-
- def test_gcm_tag_decrypt_mode(self, backend):
- key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
- iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
- aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
-
- encryptor = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv),
- backend=backend
- ).encryptor()
- encryptor.authenticate_additional_data(aad)
- encryptor.finalize()
- tag = encryptor.tag
-
- decryptor = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv, tag),
- backend=backend
- ).decryptor()
- decryptor.authenticate_additional_data(aad)
- decryptor.finalize()
-
- def test_gcm_tag_decrypt_finalize(self, backend):
- key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
- iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
- aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
-
- encryptor = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv),
- backend=backend
- ).encryptor()
- encryptor.authenticate_additional_data(aad)
- encryptor.finalize()
- tag = encryptor.tag
-
- if (
- backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
- not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
- ):
- with pytest.raises(NotImplementedError):
- decryptor = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv),
- backend=backend
- ).decryptor()
- decryptor = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv, tag=encryptor.tag),
- backend=backend
- ).decryptor()
- else:
- decryptor = base.Cipher(
- algorithms.AES(key),
- modes.GCM(iv),
- backend=backend
- ).decryptor()
- decryptor.authenticate_additional_data(aad)
-
- if (
- backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and
- not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
- ):
- with pytest.raises(NotImplementedError):
- decryptor.finalize_with_tag(tag)
- decryptor.finalize()
- else:
- decryptor.finalize_with_tag(tag)
-
- @pytest.mark.supported(
- only_if=lambda backend: (
- not backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 or
- backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
- ),
- skip_message="Not supported on OpenSSL 1.0.1",
- )
- def test_gcm_tag_decrypt_finalize_tag_length(self, backend):
- decryptor = base.Cipher(
- algorithms.AES(b"0" * 16),
- modes.GCM(b"0" * 12),
- backend=backend
- ).decryptor()
- with pytest.raises(ValueError):
- decryptor.finalize_with_tag(b"tagtooshort")
-
- def test_buffer_protocol(self, backend):
- data = bytearray(b"helloworld")
- enc = base.Cipher(
- algorithms.AES(bytearray(b"\x00" * 16)),
- modes.GCM(bytearray(b"\x00" * 12)),
- backend
- ).encryptor()
- enc.authenticate_additional_data(bytearray(b"foo"))
- ct = enc.update(data) + enc.finalize()
- dec = base.Cipher(
- algorithms.AES(bytearray(b"\x00" * 16)),
- modes.GCM(bytearray(b"\x00" * 12), enc.tag),
- backend
- ).decryptor()
- dec.authenticate_additional_data(bytearray(b"foo"))
- pt = dec.update(ct) + dec.finalize()
- assert pt == data
-
-
@pytest.mark.parametrize(
"mode",
[
@@ -484,14 +246,17 @@ class TestAESModeGCM(object):
modes.CFB(bytearray(b"\x00" * 16)),
modes.CFB8(bytearray(b"\x00" * 16)),
modes.XTS(bytearray(b"\x00" * 16)),
- ]
+ # Add a dummy mode for coverage of the cipher_supported check.
+ DummyMode(),
+ ],
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
def test_buffer_protocol_alternate_modes(mode, backend):
data = bytearray(b"sixteen_byte_msg")
- cipher = base.Cipher(
- algorithms.AES(bytearray(b"\x00" * 32)), mode, backend
- )
+ key = algorithms.AES(bytearray(os.urandom(32)))
+ if not backend.cipher_supported(key, mode):
+ pytest.skip("AES in {} mode not supported".format(mode.name))
+ cipher = base.Cipher(key, mode, backend)
enc = cipher.encryptor()
ct = enc.update(data) + enc.finalize()
dec = cipher.decryptor()
diff --git a/tests/hazmat/primitives/test_aes_gcm.py b/tests/hazmat/primitives/test_aes_gcm.py
new file mode 100644
index 000000000..8b71d1230
--- /dev/null
+++ b/tests/hazmat/primitives/test_aes_gcm.py
@@ -0,0 +1,219 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import os
+
+import pytest
+
+from cryptography.hazmat.backends.interfaces import CipherBackend
+from cryptography.hazmat.primitives.ciphers import algorithms, base, modes
+
+from .utils import generate_aead_test
+from ...utils import load_nist_vectors
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(
+ algorithms.AES(b"\x00" * 16), modes.GCM(b"\x00" * 12)
+ ),
+ skip_message="Does not support AES GCM",
+)
+@pytest.mark.requires_backend_interface(interface=CipherBackend)
+class TestAESModeGCM(object):
+ test_gcm = generate_aead_test(
+ load_nist_vectors,
+ os.path.join("ciphers", "AES", "GCM"),
+ [
+ "gcmDecrypt128.rsp",
+ "gcmDecrypt192.rsp",
+ "gcmDecrypt256.rsp",
+ "gcmEncryptExtIV128.rsp",
+ "gcmEncryptExtIV192.rsp",
+ "gcmEncryptExtIV256.rsp",
+ ],
+ algorithms.AES,
+ modes.GCM,
+ )
+
+ def test_gcm_tag_with_only_aad(self, backend):
+ key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
+ iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
+ aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
+ tag = binascii.unhexlify(b"0f247e7f9c2505de374006738018493b")
+
+ cipher = base.Cipher(
+ algorithms.AES(key), modes.GCM(iv), backend=backend
+ )
+ encryptor = cipher.encryptor()
+ encryptor.authenticate_additional_data(aad)
+ encryptor.finalize()
+ assert encryptor.tag == tag
+
+ def test_gcm_ciphertext_with_no_aad(self, backend):
+ key = binascii.unhexlify(b"e98b72a9881a84ca6b76e0f43e68647a")
+ iv = binascii.unhexlify(b"8b23299fde174053f3d652ba")
+ ct = binascii.unhexlify(b"5a3c1cf1985dbb8bed818036fdd5ab42")
+ tag = binascii.unhexlify(b"23c7ab0f952b7091cd324835043b5eb5")
+ pt = binascii.unhexlify(b"28286a321293253c3e0aa2704a278032")
+
+ cipher = base.Cipher(
+ algorithms.AES(key), modes.GCM(iv), backend=backend
+ )
+ encryptor = cipher.encryptor()
+ computed_ct = encryptor.update(pt) + encryptor.finalize()
+ assert computed_ct == ct
+ assert encryptor.tag == tag
+
+ def test_gcm_ciphertext_limit(self, backend):
+ encryptor = base.Cipher(
+ algorithms.AES(b"\x00" * 16),
+ modes.GCM(b"\x01" * 16),
+ backend=backend,
+ ).encryptor()
+ encryptor._bytes_processed = modes.GCM._MAX_ENCRYPTED_BYTES - 16
+ encryptor.update(b"0" * 16)
+ assert encryptor._bytes_processed == modes.GCM._MAX_ENCRYPTED_BYTES
+ with pytest.raises(ValueError):
+ encryptor.update(b"0")
+
+ def test_gcm_aad_limit(self, backend):
+ encryptor = base.Cipher(
+ algorithms.AES(b"\x00" * 16),
+ modes.GCM(b"\x01" * 16),
+ backend=backend,
+ ).encryptor()
+ encryptor._aad_bytes_processed = modes.GCM._MAX_AAD_BYTES - 16
+ encryptor.authenticate_additional_data(b"0" * 16)
+ assert encryptor._aad_bytes_processed == modes.GCM._MAX_AAD_BYTES
+ with pytest.raises(ValueError):
+ encryptor.authenticate_additional_data(b"0")
+
+ def test_gcm_ciphertext_increments(self, backend):
+ encryptor = base.Cipher(
+ algorithms.AES(b"\x00" * 16),
+ modes.GCM(b"\x01" * 16),
+ backend=backend,
+ ).encryptor()
+ encryptor.update(b"0" * 8)
+ assert encryptor._bytes_processed == 8
+ encryptor.update(b"0" * 7)
+ assert encryptor._bytes_processed == 15
+ encryptor.update(b"0" * 18)
+ assert encryptor._bytes_processed == 33
+
+ def test_gcm_aad_increments(self, backend):
+ encryptor = base.Cipher(
+ algorithms.AES(b"\x00" * 16),
+ modes.GCM(b"\x01" * 16),
+ backend=backend,
+ ).encryptor()
+ encryptor.authenticate_additional_data(b"0" * 8)
+ assert encryptor._aad_bytes_processed == 8
+ encryptor.authenticate_additional_data(b"0" * 18)
+ assert encryptor._aad_bytes_processed == 26
+
+ def test_gcm_tag_decrypt_none(self, backend):
+ key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
+ iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
+ aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
+
+ encryptor = base.Cipher(
+ algorithms.AES(key), modes.GCM(iv), backend=backend
+ ).encryptor()
+ encryptor.authenticate_additional_data(aad)
+ encryptor.finalize()
+
+ decryptor = base.Cipher(
+ algorithms.AES(key), modes.GCM(iv), backend=backend
+ ).decryptor()
+ decryptor.authenticate_additional_data(aad)
+ with pytest.raises(ValueError):
+ decryptor.finalize()
+
+ def test_gcm_tag_decrypt_mode(self, backend):
+ key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
+ iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
+ aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
+
+ encryptor = base.Cipher(
+ algorithms.AES(key), modes.GCM(iv), backend=backend
+ ).encryptor()
+ encryptor.authenticate_additional_data(aad)
+ encryptor.finalize()
+ tag = encryptor.tag
+
+ decryptor = base.Cipher(
+ algorithms.AES(key), modes.GCM(iv, tag), backend=backend
+ ).decryptor()
+ decryptor.authenticate_additional_data(aad)
+ decryptor.finalize()
+
+ def test_gcm_tag_decrypt_finalize(self, backend):
+ key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
+ iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
+ aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
+
+ encryptor = base.Cipher(
+ algorithms.AES(key), modes.GCM(iv), backend=backend
+ ).encryptor()
+ encryptor.authenticate_additional_data(aad)
+ encryptor.finalize()
+ tag = encryptor.tag
+
+ decryptor = base.Cipher(
+ algorithms.AES(key), modes.GCM(iv), backend=backend
+ ).decryptor()
+ decryptor.authenticate_additional_data(aad)
+
+ decryptor.finalize_with_tag(tag)
+
+ def test_gcm_tag_decrypt_finalize_tag_length(self, backend):
+ decryptor = base.Cipher(
+ algorithms.AES(b"0" * 16), modes.GCM(b"0" * 12), backend=backend
+ ).decryptor()
+ with pytest.raises(ValueError):
+ decryptor.finalize_with_tag(b"tagtooshort")
+
+ def test_buffer_protocol(self, backend):
+ data = bytearray(b"helloworld")
+ enc = base.Cipher(
+ algorithms.AES(bytearray(b"\x00" * 16)),
+ modes.GCM(bytearray(b"\x00" * 12)),
+ backend,
+ ).encryptor()
+ enc.authenticate_additional_data(bytearray(b"foo"))
+ ct = enc.update(data) + enc.finalize()
+ dec = base.Cipher(
+ algorithms.AES(bytearray(b"\x00" * 16)),
+ modes.GCM(bytearray(b"\x00" * 12), enc.tag),
+ backend,
+ ).decryptor()
+ dec.authenticate_additional_data(bytearray(b"foo"))
+ pt = dec.update(ct) + dec.finalize()
+ assert pt == data
+
+ @pytest.mark.parametrize("size", [8, 128])
+ def test_gcm_min_max_iv(self, size, backend):
+ if backend._fips_enabled:
+ # Red Hat disables non-96-bit IV support as part of its FIPS
+ # patches.
+ pytest.skip("Non-96-bit IVs unsupported in FIPS mode.")
+
+ key = os.urandom(16)
+ iv = b"\x00" * size
+
+ payload = b"data"
+ encryptor = base.Cipher(algorithms.AES(key), modes.GCM(iv)).encryptor()
+ ct = encryptor.update(payload)
+ encryptor.finalize()
+ tag = encryptor.tag
+
+ decryptor = base.Cipher(algorithms.AES(key), modes.GCM(iv)).decryptor()
+ pt = decryptor.update(ct)
+
+ decryptor.finalize_with_tag(tag)
+ assert pt == payload
diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py
index 1a1734443..de20b7098 100644
--- a/tests/hazmat/primitives/test_arc4.py
+++ b/tests/hazmat/primitives/test_arc4.py
@@ -35,7 +35,7 @@ class TestARC4(object):
"rfc-6229-128.txt",
"rfc-6229-192.txt",
"rfc-6229-256.txt",
- "arc4.txt"
+ "arc4.txt",
],
lambda key, **kwargs: algorithms.ARC4(binascii.unhexlify(key)),
)
diff --git a/tests/hazmat/primitives/test_asym_utils.py b/tests/hazmat/primitives/test_asym_utils.py
index fc9e9fd88..70bff012f 100644
--- a/tests/hazmat/primitives/test_asym_utils.py
+++ b/tests/hazmat/primitives/test_asym_utils.py
@@ -7,19 +7,10 @@ from __future__ import absolute_import, division, print_function
import pytest
from cryptography.hazmat.primitives.asymmetric.utils import (
- Prehashed, decode_dss_signature, decode_rfc6979_signature,
- encode_dss_signature, encode_rfc6979_signature,
+ Prehashed,
+ decode_dss_signature,
+ encode_dss_signature,
)
-from cryptography.utils import CryptographyDeprecationWarning
-
-
-def test_deprecated_rfc6979_signature():
- with pytest.warns(CryptographyDeprecationWarning):
- sig = encode_rfc6979_signature(1, 1)
- assert sig == b"0\x06\x02\x01\x01\x02\x01\x01"
- with pytest.warns(CryptographyDeprecationWarning):
- decoded = decode_rfc6979_signature(sig)
- assert decoded == (1, 1)
def test_dss_signature():
@@ -29,11 +20,11 @@ def test_dss_signature():
r_s1 = (
1037234182290683143945502320610861668562885151617,
- 559776156650501990899426031439030258256861634312
+ 559776156650501990899426031439030258256861634312,
)
sig2 = encode_dss_signature(*r_s1)
assert sig2 == (
- b'0-\x02\x15\x00\xb5\xaf0xg\xfb\x8bT9\x00\x13\xccg\x02\r\xdf\x1f,\x0b'
+ b"0-\x02\x15\x00\xb5\xaf0xg\xfb\x8bT9\x00\x13\xccg\x02\r\xdf\x1f,\x0b"
b'\x81\x02\x14b\r;"\xabP1D\x0c>5\xea\xb6\xf4\x81)\x8f\x9e\x9f\x08'
)
assert decode_dss_signature(sig2) == r_s1
@@ -42,10 +33,6 @@ def test_dss_signature():
assert sig3 == b"0\x06\x02\x01\x00\x02\x01\x00"
assert decode_dss_signature(sig3) == (0, 0)
- sig4 = encode_dss_signature(-1, 0)
- assert sig4 == b"0\x06\x02\x01\xFF\x02\x01\x00"
- assert decode_dss_signature(sig4) == (-1, 0)
-
def test_encode_dss_non_integer():
with pytest.raises(ValueError):
@@ -64,6 +51,11 @@ def test_encode_dss_non_integer():
encode_dss_signature("hello", "world")
+def test_encode_dss_negative():
+ with pytest.raises(ValueError):
+ encode_dss_signature(-1, 0)
+
+
def test_decode_dss_trailing_bytes():
with pytest.raises(ValueError):
decode_dss_signature(b"0\x06\x02\x01\x01\x02\x01\x01\x00\x00\x00")
diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py
index 37158f153..593199315 100644
--- a/tests/hazmat/primitives/test_block.py
+++ b/tests/hazmat/primitives/test_block.py
@@ -8,16 +8,18 @@ import binascii
import pytest
-from cryptography.exceptions import (
- AlreadyFinalized, _Reasons
-)
+from cryptography.exceptions import AlreadyFinalized, _Reasons
from cryptography.hazmat.backends.interfaces import CipherBackend
from cryptography.hazmat.primitives.ciphers import (
- Cipher, algorithms, base, modes
+ Cipher,
+ algorithms,
+ base,
+ modes,
)
from .utils import (
- generate_aead_exception_test, generate_aead_tag_exception_test
+ generate_aead_exception_test,
+ generate_aead_tag_exception_test,
)
from ...doubles import DummyCipherAlgorithm, DummyMode
from ...utils import raises_unsupported_algorithm
@@ -29,7 +31,7 @@ class TestCipher(object):
cipher = Cipher(
algorithms.AES(binascii.unhexlify(b"0" * 32)),
modes.CBC(binascii.unhexlify(b"0" * 32)),
- backend
+ backend,
)
assert isinstance(cipher.encryptor(), base.CipherContext)
@@ -37,7 +39,7 @@ class TestCipher(object):
cipher = Cipher(
algorithms.AES(binascii.unhexlify(b"0" * 32)),
modes.CBC(binascii.unhexlify(b"0" * 32)),
- backend
+ backend,
)
assert isinstance(cipher.decryptor(), base.CipherContext)
@@ -53,7 +55,7 @@ class TestCipherContext(object):
cipher = Cipher(
algorithms.AES(binascii.unhexlify(b"0" * 32)),
modes.CBC(binascii.unhexlify(b"0" * 32)),
- backend
+ backend,
)
encryptor = cipher.encryptor()
encryptor.update(b"a" * 16)
@@ -74,7 +76,7 @@ class TestCipherContext(object):
cipher = Cipher(
algorithms.AES(binascii.unhexlify(b"0" * 32)),
modes.CBC(binascii.unhexlify(b"0" * 32)),
- backend
+ backend,
)
encryptor = cipher.encryptor()
encryptor.update(b"a" * 16)
@@ -85,9 +87,7 @@ class TestCipherContext(object):
def test_unaligned_block_encryption(self, backend):
cipher = Cipher(
- algorithms.AES(binascii.unhexlify(b"0" * 32)),
- modes.ECB(),
- backend
+ algorithms.AES(binascii.unhexlify(b"0" * 32)), modes.ECB(), backend
)
encryptor = cipher.encryptor()
ct = encryptor.update(b"a" * 15)
@@ -105,9 +105,7 @@ class TestCipherContext(object):
@pytest.mark.parametrize("mode", [DummyMode(), None])
def test_nonexistent_cipher(self, backend, mode):
- cipher = Cipher(
- DummyCipherAlgorithm(), mode, backend
- )
+ cipher = Cipher(DummyCipherAlgorithm(), mode, backend)
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
cipher.encryptor()
@@ -116,9 +114,7 @@ class TestCipherContext(object):
def test_incorrectly_padded(self, backend):
cipher = Cipher(
- algorithms.AES(b"\x00" * 16),
- modes.CBC(b"\x00" * 16),
- backend
+ algorithms.AES(b"\x00" * 16), modes.CBC(b"\x00" * 16), backend
)
encryptor = cipher.encryptor()
encryptor.update(b"1")
diff --git a/tests/hazmat/primitives/test_blowfish.py b/tests/hazmat/primitives/test_blowfish.py
index 0c38b9816..5f7480ec9 100644
--- a/tests/hazmat/primitives/test_blowfish.py
+++ b/tests/hazmat/primitives/test_blowfish.py
@@ -24,7 +24,7 @@ from ...utils import load_nist_vectors
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestBlowfishModeECB(object):
- test_ECB = generate_encrypt_test(
+ test_ecb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "Blowfish"),
["bf-ecb.txt"],
@@ -41,7 +41,7 @@ class TestBlowfishModeECB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestBlowfishModeCBC(object):
- test_CBC = generate_encrypt_test(
+ test_cbc = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "Blowfish"),
["bf-cbc.txt"],
@@ -58,7 +58,7 @@ class TestBlowfishModeCBC(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestBlowfishModeOFB(object):
- test_OFB = generate_encrypt_test(
+ test_ofb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "Blowfish"),
["bf-ofb.txt"],
@@ -75,7 +75,7 @@ class TestBlowfishModeOFB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestBlowfishModeCFB(object):
- test_CFB = generate_encrypt_test(
+ test_cfb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "Blowfish"),
["bf-cfb.txt"],
diff --git a/tests/hazmat/primitives/test_camellia.py b/tests/hazmat/primitives/test_camellia.py
index 87fcfe3d1..b752345d3 100644
--- a/tests/hazmat/primitives/test_camellia.py
+++ b/tests/hazmat/primitives/test_camellia.py
@@ -13,9 +13,7 @@ from cryptography.hazmat.backends.interfaces import CipherBackend
from cryptography.hazmat.primitives.ciphers import algorithms, modes
from .utils import generate_encrypt_test
-from ...utils import (
- load_cryptrec_vectors, load_nist_vectors
-)
+from ...utils import load_cryptrec_vectors, load_nist_vectors
@pytest.mark.supported(
@@ -26,13 +24,13 @@ from ...utils import (
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestCamelliaModeECB(object):
- test_ECB = generate_encrypt_test(
+ test_ecb = generate_encrypt_test(
load_cryptrec_vectors,
os.path.join("ciphers", "Camellia"),
[
"camellia-128-ecb.txt",
"camellia-192-ecb.txt",
- "camellia-256-ecb.txt"
+ "camellia-256-ecb.txt",
],
lambda key, **kwargs: algorithms.Camellia(binascii.unhexlify(key)),
lambda **kwargs: modes.ECB(),
@@ -47,7 +45,7 @@ class TestCamelliaModeECB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestCamelliaModeCBC(object):
- test_CBC = generate_encrypt_test(
+ test_cbc = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "Camellia"),
["camellia-cbc.txt"],
@@ -64,7 +62,7 @@ class TestCamelliaModeCBC(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestCamelliaModeOFB(object):
- test_OFB = generate_encrypt_test(
+ test_ofb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "Camellia"),
["camellia-ofb.txt"],
@@ -81,7 +79,7 @@ class TestCamelliaModeOFB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestCamelliaModeCFB(object):
- test_CFB = generate_encrypt_test(
+ test_cfb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "Camellia"),
["camellia-cfb.txt"],
diff --git a/tests/hazmat/primitives/test_cast5.py b/tests/hazmat/primitives/test_cast5.py
index ec51659d0..eff5d252f 100644
--- a/tests/hazmat/primitives/test_cast5.py
+++ b/tests/hazmat/primitives/test_cast5.py
@@ -24,7 +24,7 @@ from ...utils import load_nist_vectors
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestCAST5ModeECB(object):
- test_ECB = generate_encrypt_test(
+ test_ecb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "CAST5"),
["cast5-ecb.txt"],
@@ -41,12 +41,12 @@ class TestCAST5ModeECB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestCAST5ModeCBC(object):
- test_CBC = generate_encrypt_test(
+ test_cbc = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "CAST5"),
["cast5-cbc.txt"],
lambda key, **kwargs: algorithms.CAST5(binascii.unhexlify((key))),
- lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv))
+ lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)),
)
@@ -58,12 +58,12 @@ class TestCAST5ModeCBC(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestCAST5ModeOFB(object):
- test_OFB = generate_encrypt_test(
+ test_ofb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "CAST5"),
["cast5-ofb.txt"],
lambda key, **kwargs: algorithms.CAST5(binascii.unhexlify((key))),
- lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv))
+ lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv)),
)
@@ -75,10 +75,10 @@ class TestCAST5ModeOFB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestCAST5ModeCFB(object):
- test_CFB = generate_encrypt_test(
+ test_cfb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "CAST5"),
["cast5-cfb.txt"],
lambda key, **kwargs: algorithms.CAST5(binascii.unhexlify((key))),
- lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv))
+ lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)),
)
diff --git a/tests/hazmat/primitives/test_chacha20.py b/tests/hazmat/primitives/test_chacha20.py
index 7c475c0f7..cb12d3c91 100644
--- a/tests/hazmat/primitives/test_chacha20.py
+++ b/tests/hazmat/primitives/test_chacha20.py
@@ -30,8 +30,8 @@ class TestChaCha20(object):
_load_all_params(
os.path.join("ciphers", "ChaCha20"),
["rfc7539.txt"],
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_vectors(self, vector, backend):
key = binascii.unhexlify(vector["key"])
@@ -47,9 +47,7 @@ class TestChaCha20(object):
def test_buffer_protocol(self, backend):
key = bytearray(os.urandom(32))
nonce = bytearray(os.urandom(16))
- cipher = Cipher(
- algorithms.ChaCha20(key, nonce), None, backend
- )
+ cipher = Cipher(algorithms.ChaCha20(key, nonce), None, backend)
enc = cipher.encryptor()
ct = enc.update(bytearray(b"hello")) + enc.finalize()
dec = cipher.decryptor()
diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py
index f29ba9a91..a9219fe99 100644
--- a/tests/hazmat/primitives/test_ciphers.py
+++ b/tests/hazmat/primitives/test_ciphers.py
@@ -14,20 +14,28 @@ from cryptography.hazmat.backends.interfaces import CipherBackend
from cryptography.hazmat.primitives import ciphers
from cryptography.hazmat.primitives.ciphers import modes
from cryptography.hazmat.primitives.ciphers.algorithms import (
- AES, ARC4, Blowfish, CAST5, Camellia, IDEA, SEED, TripleDES
+ AES,
+ ARC4,
+ Blowfish,
+ CAST5,
+ Camellia,
+ IDEA,
+ SEED,
+ TripleDES,
)
from ...utils import (
- load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
class TestAES(object):
- @pytest.mark.parametrize(("key", "keysize"), [
- (b"0" * 32, 128),
- (b"0" * 48, 192),
- (b"0" * 64, 256),
- ])
+ @pytest.mark.parametrize(
+ ("key", "keysize"),
+ [(b"0" * 32, 128), (b"0" * 48, 192), (b"0" * 64, 256)],
+ )
def test_key_size(self, key, keysize):
cipher = AES(binascii.unhexlify(key))
assert cipher.key_size == keysize
@@ -44,8 +52,7 @@ class TestAES(object):
class TestAESXTS(object):
@pytest.mark.requires_backend_interface(interface=CipherBackend)
@pytest.mark.parametrize(
- "mode",
- (modes.CBC, modes.CTR, modes.CFB, modes.CFB8, modes.OFB)
+ "mode", (modes.CBC, modes.CTR, modes.CFB, modes.CFB8, modes.OFB)
)
def test_invalid_key_size_with_mode(self, mode, backend):
with pytest.raises(ValueError):
@@ -65,12 +72,18 @@ class TestAESXTS(object):
ciphers.Cipher(AES(b"0" * 16), modes.XTS(b"0" * 16), backend)
+class TestGCM(object):
+ @pytest.mark.parametrize("size", [7, 129])
+ def test_gcm_min_max(self, size):
+ with pytest.raises(ValueError):
+ modes.GCM(b"0" * size)
+
+
class TestCamellia(object):
- @pytest.mark.parametrize(("key", "keysize"), [
- (b"0" * 32, 128),
- (b"0" * 48, 192),
- (b"0" * 64, 256),
- ])
+ @pytest.mark.parametrize(
+ ("key", "keysize"),
+ [(b"0" * 32, 128), (b"0" * 48, 192), (b"0" * 64, 256)],
+ )
def test_key_size(self, key, keysize):
cipher = Camellia(binascii.unhexlify(key))
assert cipher.key_size == keysize
@@ -85,11 +98,7 @@ class TestCamellia(object):
class TestTripleDES(object):
- @pytest.mark.parametrize("key", [
- b"0" * 16,
- b"0" * 32,
- b"0" * 48,
- ])
+ @pytest.mark.parametrize("key", [b"0" * 16, b"0" * 32, b"0" * 48])
def test_key_size(self, key):
cipher = TripleDES(binascii.unhexlify(key))
assert cipher.key_size == 192
@@ -104,9 +113,10 @@ class TestTripleDES(object):
class TestBlowfish(object):
- @pytest.mark.parametrize(("key", "keysize"), [
- (b"0" * (keysize // 4), keysize) for keysize in range(32, 449, 8)
- ])
+ @pytest.mark.parametrize(
+ ("key", "keysize"),
+ [(b"0" * (keysize // 4), keysize) for keysize in range(32, 449, 8)],
+ )
def test_key_size(self, key, keysize):
cipher = Blowfish(binascii.unhexlify(key))
assert cipher.key_size == keysize
@@ -121,9 +131,10 @@ class TestBlowfish(object):
class TestCAST5(object):
- @pytest.mark.parametrize(("key", "keysize"), [
- (b"0" * (keysize // 4), keysize) for keysize in range(40, 129, 8)
- ])
+ @pytest.mark.parametrize(
+ ("key", "keysize"),
+ [(b"0" * (keysize // 4), keysize) for keysize in range(40, 129, 8)],
+ )
def test_key_size(self, key, keysize):
cipher = CAST5(binascii.unhexlify(key))
assert cipher.key_size == keysize
@@ -138,15 +149,18 @@ class TestCAST5(object):
class TestARC4(object):
- @pytest.mark.parametrize(("key", "keysize"), [
- (b"0" * 10, 40),
- (b"0" * 14, 56),
- (b"0" * 16, 64),
- (b"0" * 20, 80),
- (b"0" * 32, 128),
- (b"0" * 48, 192),
- (b"0" * 64, 256),
- ])
+ @pytest.mark.parametrize(
+ ("key", "keysize"),
+ [
+ (b"0" * 10, 40),
+ (b"0" * 14, 56),
+ (b"0" * 16, 64),
+ (b"0" * 20, 80),
+ (b"0" * 32, 128),
+ (b"0" * 48, 192),
+ (b"0" * 64, 256),
+ ],
+ )
def test_key_size(self, key, keysize):
cipher = ARC4(binascii.unhexlify(key))
assert cipher.key_size == keysize
@@ -207,8 +221,8 @@ class TestCipherUpdateInto(object):
"params",
load_vectors_from_file(
os.path.join("ciphers", "AES", "ECB", "ECBGFSbox128.rsp"),
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_update_into(self, params, backend):
key = binascii.unhexlify(params["key"])
@@ -272,8 +286,8 @@ class TestCipherUpdateInto(object):
"params",
load_vectors_from_file(
os.path.join("ciphers", "AES", "ECB", "ECBGFSbox128.rsp"),
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_update_into_multiple_calls(self, params, backend):
key = binascii.unhexlify(params["key"])
@@ -309,3 +323,29 @@ class TestCipherUpdateInto(object):
buf = bytearray(5)
with pytest.raises(ValueError):
encryptor.update_into(b"testing", buf)
+
+ def test_update_into_auto_chunking(self, backend, monkeypatch):
+ key = b"\x00" * 16
+ c = ciphers.Cipher(AES(key), modes.ECB(), backend)
+ encryptor = c.encryptor()
+ # Lower max chunk size so we can test chunking
+ monkeypatch.setattr(encryptor._ctx, "_MAX_CHUNK_SIZE", 40)
+ buf = bytearray(527)
+ pt = b"abcdefghijklmnopqrstuvwxyz012345" * 16 # 512 bytes
+ processed = encryptor.update_into(pt, buf)
+ assert processed == 512
+ decryptor = c.decryptor()
+ # Change max chunk size to verify alternate boundaries don't matter
+ monkeypatch.setattr(decryptor._ctx, "_MAX_CHUNK_SIZE", 73)
+ decbuf = bytearray(527)
+ decprocessed = decryptor.update_into(buf[:processed], decbuf)
+ assert decbuf[:decprocessed] == pt
+
+ def test_max_chunk_size_fits_in_int32(self, backend):
+ # max chunk must fit in signed int32 or else a call large enough to
+ # cause chunking will result in the very OverflowError we want to
+ # avoid with chunking.
+ key = b"\x00" * 16
+ c = ciphers.Cipher(AES(key), modes.ECB(), backend)
+ encryptor = c.encryptor()
+ backend._ffi.new("int *", encryptor._ctx._MAX_CHUNK_SIZE)
diff --git a/tests/hazmat/primitives/test_cmac.py b/tests/hazmat/primitives/test_cmac.py
index e319396d6..e4a35df62 100644
--- a/tests/hazmat/primitives/test_cmac.py
+++ b/tests/hazmat/primitives/test_cmac.py
@@ -9,32 +9,42 @@ import binascii
import pytest
from cryptography.exceptions import (
- AlreadyFinalized, InvalidSignature, _Reasons
+ AlreadyFinalized,
+ InvalidSignature,
+ _Reasons,
)
from cryptography.hazmat.backends.interfaces import CMACBackend
from cryptography.hazmat.primitives.ciphers.algorithms import (
- AES, ARC4, TripleDES
+ AES,
+ ARC4,
+ TripleDES,
)
from cryptography.hazmat.primitives.cmac import CMAC
from ...utils import (
- load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
vectors_aes128 = load_vectors_from_file(
- "CMAC/nist-800-38b-aes128.txt", load_nist_vectors)
+ "CMAC/nist-800-38b-aes128.txt", load_nist_vectors
+)
vectors_aes192 = load_vectors_from_file(
- "CMAC/nist-800-38b-aes192.txt", load_nist_vectors)
+ "CMAC/nist-800-38b-aes192.txt", load_nist_vectors
+)
vectors_aes256 = load_vectors_from_file(
- "CMAC/nist-800-38b-aes256.txt", load_nist_vectors)
+ "CMAC/nist-800-38b-aes256.txt", load_nist_vectors
+)
vectors_aes = vectors_aes128 + vectors_aes192 + vectors_aes256
vectors_3des = load_vectors_from_file(
- "CMAC/nist-800-38b-3des.txt", load_nist_vectors)
+ "CMAC/nist-800-38b-3des.txt", load_nist_vectors
+)
fake_key = b"\x00" * 16
@@ -43,8 +53,9 @@ fake_key = b"\x00" * 16
class TestCMAC(object):
@pytest.mark.supported(
only_if=lambda backend: backend.cmac_algorithm_supported(
- AES(fake_key)),
- skip_message="Does not support CMAC."
+ AES(fake_key)
+ ),
+ skip_message="Does not support CMAC.",
)
@pytest.mark.parametrize("params", vectors_aes)
def test_aes_generate(self, backend, params):
@@ -58,8 +69,9 @@ class TestCMAC(object):
@pytest.mark.supported(
only_if=lambda backend: backend.cmac_algorithm_supported(
- AES(fake_key)),
- skip_message="Does not support CMAC."
+ AES(fake_key)
+ ),
+ skip_message="Does not support CMAC.",
)
@pytest.mark.parametrize("params", vectors_aes)
def test_aes_verify(self, backend, params):
@@ -73,8 +85,9 @@ class TestCMAC(object):
@pytest.mark.supported(
only_if=lambda backend: backend.cmac_algorithm_supported(
- TripleDES(fake_key)),
- skip_message="Does not support CMAC."
+ TripleDES(fake_key)
+ ),
+ skip_message="Does not support CMAC.",
)
@pytest.mark.parametrize("params", vectors_3des)
def test_3des_generate(self, backend, params):
@@ -93,8 +106,9 @@ class TestCMAC(object):
@pytest.mark.supported(
only_if=lambda backend: backend.cmac_algorithm_supported(
- TripleDES(fake_key)),
- skip_message="Does not support CMAC."
+ TripleDES(fake_key)
+ ),
+ skip_message="Does not support CMAC.",
)
@pytest.mark.parametrize("params", vectors_3des)
def test_3des_verify(self, backend, params):
@@ -113,8 +127,9 @@ class TestCMAC(object):
@pytest.mark.supported(
only_if=lambda backend: backend.cmac_algorithm_supported(
- AES(fake_key)),
- skip_message="Does not support CMAC."
+ AES(fake_key)
+ ),
+ skip_message="Does not support CMAC.",
)
def test_invalid_verify(self, backend):
key = b"2b7e151628aed2a6abf7158809cf4f3c"
@@ -125,9 +140,8 @@ class TestCMAC(object):
cmac.verify(b"foobar")
@pytest.mark.supported(
- only_if=lambda backend: backend.cipher_supported(
- ARC4(fake_key), None),
- skip_message="Does not support CMAC."
+ only_if=lambda backend: backend.cipher_supported(ARC4(fake_key), None),
+ skip_message="Does not support CMAC.",
)
def test_invalid_algorithm(self, backend):
key = b"0102030405"
@@ -136,8 +150,9 @@ class TestCMAC(object):
@pytest.mark.supported(
only_if=lambda backend: backend.cmac_algorithm_supported(
- AES(fake_key)),
- skip_message="Does not support CMAC."
+ AES(fake_key)
+ ),
+ skip_message="Does not support CMAC.",
)
def test_raises_after_finalize(self, backend):
key = b"2b7e151628aed2a6abf7158809cf4f3c"
@@ -158,23 +173,25 @@ class TestCMAC(object):
@pytest.mark.supported(
only_if=lambda backend: backend.cmac_algorithm_supported(
- AES(fake_key)),
- skip_message="Does not support CMAC."
+ AES(fake_key)
+ ),
+ skip_message="Does not support CMAC.",
)
def test_verify_reject_unicode(self, backend):
key = b"2b7e151628aed2a6abf7158809cf4f3c"
cmac = CMAC(AES(key), backend)
with pytest.raises(TypeError):
- cmac.update(u'')
+ cmac.update(u"")
with pytest.raises(TypeError):
- cmac.verify(u'')
+ cmac.verify(u"")
@pytest.mark.supported(
only_if=lambda backend: backend.cmac_algorithm_supported(
- AES(fake_key)),
- skip_message="Does not support CMAC."
+ AES(fake_key)
+ ),
+ skip_message="Does not support CMAC.",
)
def test_copy_with_backend(self, backend):
key = b"2b7e151628aed2a6abf7158809cf4f3c"
@@ -185,8 +202,9 @@ class TestCMAC(object):
@pytest.mark.supported(
only_if=lambda backend: backend.cmac_algorithm_supported(
- AES(fake_key)),
- skip_message="Does not support CMAC."
+ AES(fake_key)
+ ),
+ skip_message="Does not support CMAC.",
)
def test_buffer_protocol(self, backend):
key = bytearray(b"2b7e151628aed2a6abf7158809cf4f3c")
diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py
index 673150999..271e01175 100644
--- a/tests/hazmat/primitives/test_concatkdf.py
+++ b/tests/hazmat/primitives/test_concatkdf.py
@@ -8,9 +8,7 @@ import binascii
import pytest
-from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, _Reasons
-)
+from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.backends.interfaces import HashBackend
from cryptography.hazmat.primitives import hashes
@@ -102,38 +100,26 @@ class TestConcatKDFHash(object):
def test_unicode_typeerror(self, backend):
with pytest.raises(TypeError):
ConcatKDFHash(
- hashes.SHA256(),
- 16,
- otherinfo=u"foo",
- backend=backend
+ hashes.SHA256(), 16, otherinfo=u"foo", backend=backend
)
with pytest.raises(TypeError):
ckdf = ConcatKDFHash(
- hashes.SHA256(),
- 16,
- otherinfo=None,
- backend=backend
+ hashes.SHA256(), 16, otherinfo=None, backend=backend
)
ckdf.derive(u"foo")
with pytest.raises(TypeError):
ckdf = ConcatKDFHash(
- hashes.SHA256(),
- 16,
- otherinfo=None,
- backend=backend
+ hashes.SHA256(), 16, otherinfo=None, backend=backend
)
ckdf.verify(u"foo", b"bar")
with pytest.raises(TypeError):
ckdf = ConcatKDFHash(
- hashes.SHA256(),
- 16,
- otherinfo=None,
- backend=backend
+ hashes.SHA256(), 16, otherinfo=None, backend=backend
)
ckdf.verify(b"foo", u"bar")
@@ -162,8 +148,10 @@ class TestConcatKDFHMAC(object):
b"8f0af7fce1d045edbc5790931e8d5ca79c73"
)
- okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7"
- b"605323ce2f39bf27eaaac8b34cf89f2f")
+ okm = binascii.unhexlify(
+ b"64ce901db10d558661f10b6836a122a7"
+ b"605323ce2f39bf27eaaac8b34cf89f2f"
+ )
oinfo = binascii.unhexlify(
b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c"
@@ -181,8 +169,10 @@ class TestConcatKDFHMAC(object):
b"8f0af7fce1d045edbc5790931e8d5ca79c73"
)
- okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7"
- b"605323ce2f39bf27eaaac8b34cf89f2f")
+ okm = binascii.unhexlify(
+ b"64ce901db10d558661f10b6836a122a7"
+ b"605323ce2f39bf27eaaac8b34cf89f2f"
+ )
oinfo = binascii.unhexlify(
b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c"
@@ -200,8 +190,10 @@ class TestConcatKDFHMAC(object):
b"8f0af7fce1d045edbc5790931e8d5ca79c73"
)
- okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7"
- b"605323ce2f39bf27eaaac8b34cf89f2f")
+ okm = binascii.unhexlify(
+ b"64ce901db10d558661f10b6836a122a7"
+ b"605323ce2f39bf27eaaac8b34cf89f2f"
+ )
oinfo = binascii.unhexlify(
b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c"
@@ -221,8 +213,10 @@ class TestConcatKDFHMAC(object):
b"8f0af7fce1d045edbc5790931e8d5ca79c73"
)
- okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7"
- b"605323ce2f39bf27eaaac8b34cf89f2f")
+ okm = binascii.unhexlify(
+ b"64ce901db10d558661f10b6836a122a7"
+ b"605323ce2f39bf27eaaac8b34cf89f2f"
+ )
oinfo = binascii.unhexlify(
b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c"
@@ -254,45 +248,38 @@ class TestConcatKDFHMAC(object):
with pytest.raises(TypeError):
ConcatKDFHMAC(
hashes.SHA256(),
- 16, salt=u"foo",
+ 16,
+ salt=u"foo",
otherinfo=None,
- backend=backend
+ backend=backend,
)
with pytest.raises(TypeError):
ConcatKDFHMAC(
hashes.SHA256(),
- 16, salt=None,
+ 16,
+ salt=None,
otherinfo=u"foo",
- backend=backend
+ backend=backend,
)
with pytest.raises(TypeError):
ckdf = ConcatKDFHMAC(
- hashes.SHA256(),
- 16, salt=None,
- otherinfo=None,
- backend=backend
+ hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend
)
ckdf.derive(u"foo")
with pytest.raises(TypeError):
ckdf = ConcatKDFHMAC(
- hashes.SHA256(),
- 16, salt=None,
- otherinfo=None,
- backend=backend
+ hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend
)
ckdf.verify(u"foo", b"bar")
with pytest.raises(TypeError):
ckdf = ConcatKDFHMAC(
- hashes.SHA256(),
- 16, salt=None,
- otherinfo=None,
- backend=backend
+ hashes.SHA256(), 16, salt=None, otherinfo=None, backend=backend
)
ckdf.verify(b"foo", u"bar")
diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py
index c667cd16e..bc5ed8fb0 100644
--- a/tests/hazmat/primitives/test_dh.py
+++ b/tests/hazmat/primitives/test_dh.py
@@ -11,119 +11,114 @@ import os
import pytest
from cryptography.hazmat.backends.interfaces import (
- DERSerializationBackend, DHBackend, PEMSerializationBackend)
+ DERSerializationBackend,
+ DHBackend,
+ PEMSerializationBackend,
+)
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import dh
from cryptography.utils import int_from_bytes
+from .fixtures_dh import FFDH3072_P
from ...doubles import DummyKeySerializationEncryption
from ...utils import load_nist_vectors, load_vectors_from_file
+# RFC 3526
+P_1536 = int(
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
+ 16,
+)
+
def _skip_dhx_unsupported(backend, is_dhx):
if not is_dhx:
return
if not backend.dh_x942_serialization_supported():
- pytest.skip(
- "DH x9.42 serialization is not supported"
- )
+ pytest.skip("DH x9.42 serialization is not supported")
def test_dh_parameternumbers():
- params = dh.DHParameterNumbers(
- 65537, 2
- )
+ params = dh.DHParameterNumbers(P_1536, 2)
- assert params.p == 65537
+ assert params.p == P_1536
assert params.g == 2
with pytest.raises(TypeError):
- dh.DHParameterNumbers(
- None, 2
- )
+ dh.DHParameterNumbers(None, 2)
with pytest.raises(TypeError):
- dh.DHParameterNumbers(
- 65537, None
- )
+ dh.DHParameterNumbers(P_1536, None)
with pytest.raises(TypeError):
- dh.DHParameterNumbers(
- None, None
- )
+ dh.DHParameterNumbers(None, None)
with pytest.raises(ValueError):
- dh.DHParameterNumbers(
- 65537, 1
- )
+ dh.DHParameterNumbers(P_1536, 1)
- params = dh.DHParameterNumbers(
- 65537, 7, 1245
- )
+ # p too small
+ with pytest.raises(ValueError):
+ dh.DHParameterNumbers(65537, 2)
+
+ params = dh.DHParameterNumbers(P_1536, 7, 1245)
- assert params.p == 65537
+ assert params.p == P_1536
assert params.g == 7
assert params.q == 1245
with pytest.raises(TypeError):
- dh.DHParameterNumbers(
- 65537, 2, "hello"
- )
+ dh.DHParameterNumbers(P_1536, 2, "hello")
def test_dh_numbers():
- params = dh.DHParameterNumbers(
- 65537, 2
- )
+ params = dh.DHParameterNumbers(P_1536, 2)
- public = dh.DHPublicNumbers(
- 1, params
- )
+ public = dh.DHPublicNumbers(1, params)
assert public.parameter_numbers is params
assert public.y == 1
with pytest.raises(TypeError):
- dh.DHPublicNumbers(
- 1, None
- )
+ dh.DHPublicNumbers(1, None)
with pytest.raises(TypeError):
- dh.DHPublicNumbers(
- None, params
- )
+ dh.DHPublicNumbers(None, params)
- private = dh.DHPrivateNumbers(
- 1, public
- )
+ private = dh.DHPrivateNumbers(1, public)
assert private.public_numbers is public
assert private.x == 1
with pytest.raises(TypeError):
- dh.DHPrivateNumbers(
- 1, None
- )
+ dh.DHPrivateNumbers(1, None)
with pytest.raises(TypeError):
- dh.DHPrivateNumbers(
- None, public
- )
+ dh.DHPrivateNumbers(None, public)
def test_dh_parameter_numbers_equality():
- assert dh.DHParameterNumbers(65537, 2) == dh.DHParameterNumbers(65537, 2)
- assert dh.DHParameterNumbers(65537, 7, 12345) == dh.DHParameterNumbers(
- 65537, 7, 12345)
- assert dh.DHParameterNumbers(6, 2) != dh.DHParameterNumbers(65537, 2)
- assert dh.DHParameterNumbers(65537, 2, 123) != dh.DHParameterNumbers(
- 65537, 2, 456)
- assert dh.DHParameterNumbers(65537, 5) != dh.DHParameterNumbers(65537, 2)
- assert dh.DHParameterNumbers(65537, 2) != object()
+ assert dh.DHParameterNumbers(P_1536, 2) == dh.DHParameterNumbers(P_1536, 2)
+ assert dh.DHParameterNumbers(P_1536, 7, 12345) == dh.DHParameterNumbers(
+ P_1536, 7, 12345
+ )
+ assert dh.DHParameterNumbers(P_1536 + 2, 2) != dh.DHParameterNumbers(
+ P_1536, 2
+ )
+ assert dh.DHParameterNumbers(P_1536, 2, 123) != dh.DHParameterNumbers(
+ P_1536, 2, 456
+ )
+ assert dh.DHParameterNumbers(P_1536, 5) != dh.DHParameterNumbers(P_1536, 2)
+ assert dh.DHParameterNumbers(P_1536, 2) != object()
def test_dh_private_numbers_equality():
- params = dh.DHParameterNumbers(65537, 2)
+ params = dh.DHParameterNumbers(P_1536, 2)
public = dh.DHPublicNumbers(1, params)
private = dh.DHPrivateNumbers(2, public)
@@ -131,18 +126,18 @@ def test_dh_private_numbers_equality():
assert private != dh.DHPrivateNumbers(0, public)
assert private != dh.DHPrivateNumbers(2, dh.DHPublicNumbers(0, params))
assert private != dh.DHPrivateNumbers(
- 2, dh.DHPublicNumbers(1, dh.DHParameterNumbers(65537, 5))
+ 2, dh.DHPublicNumbers(1, dh.DHParameterNumbers(P_1536, 5))
)
assert private != object()
def test_dh_public_numbers_equality():
- params = dh.DHParameterNumbers(65537, 2)
+ params = dh.DHParameterNumbers(P_1536, 2)
public = dh.DHPublicNumbers(1, params)
assert public == dh.DHPublicNumbers(1, params)
assert public != dh.DHPublicNumbers(0, params)
- assert public != dh.DHPublicNumbers(1, dh.DHParameterNumbers(65537, 5))
+ assert public != dh.DHPublicNumbers(1, dh.DHParameterNumbers(P_1536, 5))
assert public != object()
@@ -156,19 +151,33 @@ class TestDH(object):
with pytest.raises(ValueError):
dh.generate_parameters(7, 512, backend)
+ @pytest.mark.skip_fips(reason="non-FIPS parameters")
def test_dh_parameters_supported(self, backend):
- assert backend.dh_parameters_supported(23, 5)
- assert not backend.dh_parameters_supported(23, 18)
+ valid_p = int(
+ b"907c7211ae61aaaba1825ff53b6cb71ac6df9f1a424c033f4a0a41ac42fad3a9"
+ b"bcfc7f938a269710ed69e330523e4039029b7900977c740990d46efed79b9bbe"
+ b"73505ae878808944ce4d9c6c52daecc0a87dc889c53499be93db8551ee685f30"
+ b"349bf1b443d4ebaee0d5e8b441a40d4e8178f8f612f657a5eb91e0a8e"
+ b"107755f",
+ 16,
+ )
+ assert backend.dh_parameters_supported(valid_p, 5)
+ assert not backend.dh_parameters_supported(23, 22)
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
- os.path.join("asymmetric", "DH", "rfc3526.txt"),
- load_nist_vectors
- )
+ os.path.join("asymmetric", "DH", "rfc3526.txt"), load_nist_vectors
+ ),
)
def test_dh_parameters_allows_rfc3526_groups(self, backend, vector):
- p = int_from_bytes(binascii.unhexlify(vector["p"]), 'big')
+ p = int_from_bytes(binascii.unhexlify(vector["p"]), "big")
+ if (
+ backend._fips_enabled
+ and p.bit_length() < backend._fips_dh_min_modulus
+ ):
+ pytest.skip("modulus too small for FIPS mode")
+
params = dh.DHParameterNumbers(p, int(vector["g"]))
param = params.parameters(backend)
key = param.generate_private_key()
@@ -178,22 +187,26 @@ class TestDH(object):
roundtripped_key = key.private_numbers().private_key(backend)
assert key.private_numbers() == roundtripped_key.private_numbers()
+ @pytest.mark.skip_fips(reason="non-FIPS parameters")
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
- os.path.join("asymmetric", "DH", "RFC5114.txt"),
- load_nist_vectors))
+ os.path.join("asymmetric", "DH", "RFC5114.txt"), load_nist_vectors
+ ),
+ )
def test_dh_parameters_supported_with_q(self, backend, vector):
- assert backend.dh_parameters_supported(int(vector["p"], 16),
- int(vector["g"], 16),
- int(vector["q"], 16))
+ assert backend.dh_parameters_supported(
+ int(vector["p"], 16), int(vector["g"], 16), int(vector["q"], 16)
+ )
+ @pytest.mark.skip_fips(reason="modulus too small for FIPS")
@pytest.mark.parametrize("with_q", [False, True])
def test_convert_to_numbers(self, backend, with_q):
if with_q:
vector = load_vectors_from_file(
os.path.join("asymmetric", "DH", "RFC5114.txt"),
- load_nist_vectors)[0]
+ load_nist_vectors,
+ )[0]
p = int(vector["p"], 16)
g = int(vector["g"], 16)
q = int(vector["q"], 16)
@@ -214,32 +227,35 @@ class TestDH(object):
deserialized_public = public.public_key(backend)
deserialized_private = private.private_key(backend)
- assert isinstance(deserialized_params,
- dh.DHParametersWithSerialization)
- assert isinstance(deserialized_public,
- dh.DHPublicKeyWithSerialization)
- assert isinstance(deserialized_private,
- dh.DHPrivateKeyWithSerialization)
+ assert isinstance(
+ deserialized_params, dh.DHParametersWithSerialization
+ )
+ assert isinstance(deserialized_public, dh.DHPublicKeyWithSerialization)
+ assert isinstance(
+ deserialized_private, dh.DHPrivateKeyWithSerialization
+ )
+ @pytest.mark.skip_fips(reason="FIPS requires specific parameters")
def test_numbers_unsupported_parameters(self, backend):
- # p is set to 21 because when calling private_key we want it to
- # fail the DH_check call OpenSSL does. Originally this was 23, but
- # we are allowing p % 24 to == 23 with this PR (see #3768 for more)
- # By setting it to 21 it fails later in DH_check in a primality check
- # which triggers the code path we want to test
- params = dh.DHParameterNumbers(21, 2)
+ # p is set to P_1536 + 1 because when calling private_key we want it to
+ # fail the DH_check call OpenSSL does, but we specifically want it to
+ # fail such that we don't get a DH_NOT_SUITABLE_GENERATOR. We can cause
+ # this by making sure p is not prime.
+ params = dh.DHParameterNumbers(P_1536 + 1, 2)
public = dh.DHPublicNumbers(1, params)
private = dh.DHPrivateNumbers(2, public)
with pytest.raises(ValueError):
private.private_key(backend)
+ @pytest.mark.skip_fips(reason="FIPS requires key size >= 2048")
@pytest.mark.parametrize("with_q", [False, True])
def test_generate_dh(self, backend, with_q):
if with_q:
vector = load_vectors_from_file(
os.path.join("asymmetric", "DH", "RFC5114.txt"),
- load_nist_vectors)[0]
+ load_nist_vectors,
+ )[0]
p = int(vector["p"], 16)
g = int(vector["g"], 16)
q = int(vector["q"], 16)
@@ -274,7 +290,7 @@ class TestDH(object):
assert isinstance(key.parameters(), dh.DHParameters)
def test_exchange(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
assert isinstance(parameters, dh.DHParameters)
key1 = parameters.generate_private_key()
@@ -282,65 +298,82 @@ class TestDH(object):
symkey1 = key1.exchange(key2.public_key())
assert symkey1
- assert len(symkey1) == 512 // 8
+ assert len(symkey1) == 3072 // 8
symkey2 = key2.exchange(key1.public_key())
assert symkey1 == symkey2
def test_exchange_algorithm(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
-
+ parameters = FFDH3072_P.parameters(backend)
key1 = parameters.generate_private_key()
key2 = parameters.generate_private_key()
shared_key_bytes = key2.exchange(key1.public_key())
- symkey = int_from_bytes(shared_key_bytes, 'big')
+ symkey = int_from_bytes(shared_key_bytes, "big")
- symkey_manual = pow(key1.public_key().public_numbers().y,
- key2.private_numbers().x,
- parameters.parameter_numbers().p)
+ symkey_manual = pow(
+ key1.public_key().public_numbers().y,
+ key2.private_numbers().x,
+ parameters.parameter_numbers().p,
+ )
assert symkey == symkey_manual
+ @pytest.mark.skip_fips(reason="key_size too small for FIPS")
def test_symmetric_key_padding(self, backend):
"""
This test has specific parameters that produce a symmetric key
In length 63 bytes instead 64. We make sure here that we add
padding to the key.
"""
- p = int("11859949538425015739337467917303613431031019140213666"
- "129025407300654026585086345323066284800963463204246390"
- "256567934582260424238844463330887962689642467123")
+ p = int(
+ "11859949538425015739337467917303613431031019140213666"
+ "129025407300654026585086345323066284800963463204246390"
+ "256567934582260424238844463330887962689642467123"
+ )
g = 2
- y = int("32155788395534640648739966373159697798396966919821525"
- "72238852825117261342483718574508213761865276905503199"
- "969908098203345481366464874759377454476688391248")
- x = int("409364065449673443397833358558926598469347813468816037"
- "268451847116982490733450463194921405069999008617231539"
- "7147035896687401350877308899732826446337707128")
+ y = int(
+ "32155788395534640648739966373159697798396966919821525"
+ "72238852825117261342483718574508213761865276905503199"
+ "969908098203345481366464874759377454476688391248"
+ )
+ x = int(
+ "409364065449673443397833358558926598469347813468816037"
+ "268451847116982490733450463194921405069999008617231539"
+ "7147035896687401350877308899732826446337707128"
+ )
parameters = dh.DHParameterNumbers(p, g)
public = dh.DHPublicNumbers(y, parameters)
private = dh.DHPrivateNumbers(x, public)
key = private.private_key(backend)
symkey = key.exchange(public.public_key(backend))
assert len(symkey) == 512 // 8
- assert symkey[:1] == b'\x00'
+ assert symkey[:1] == b"\x00"
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
os.path.join("asymmetric", "DH", "bad_exchange.txt"),
- load_nist_vectors))
+ load_nist_vectors,
+ ),
+ )
def test_bad_exchange(self, backend, vector):
- parameters1 = dh.DHParameterNumbers(int(vector["p1"]),
- int(vector["g"]))
+ if (
+ backend._fips_enabled
+ and int(vector["p1"]) < backend._fips_dh_min_modulus
+ ):
+ pytest.skip("modulus too small for FIPS mode")
+ parameters1 = dh.DHParameterNumbers(
+ int(vector["p1"]), int(vector["g"])
+ )
public1 = dh.DHPublicNumbers(int(vector["y1"]), parameters1)
private1 = dh.DHPrivateNumbers(int(vector["x1"]), public1)
key1 = private1.private_key(backend)
pub_key1 = key1.public_key()
- parameters2 = dh.DHParameterNumbers(int(vector["p2"]),
- int(vector["g"]))
+ parameters2 = dh.DHParameterNumbers(
+ int(vector["p2"]), int(vector["g"])
+ )
public2 = dh.DHPublicNumbers(int(vector["y2"]), parameters2)
private2 = dh.DHPrivateNumbers(int(vector["x2"]), public2)
key2 = private2.private_key(backend)
@@ -357,30 +390,51 @@ class TestDH(object):
assert symkey1 != symkey2
+ @pytest.mark.skip_fips(reason="key_size too small for FIPS")
+ def test_load_256bit_key_from_pkcs8(self, backend):
+ data = load_vectors_from_file(
+ os.path.join("asymmetric", "DH", "dh_key_256.pem"),
+ lambda pemfile: pemfile.read(),
+ mode="rb",
+ )
+ key = serialization.load_pem_private_key(data, None, backend)
+ assert key.key_size == 256
+
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
- os.path.join("asymmetric", "DH", "vec.txt"),
- load_nist_vectors))
+ os.path.join("asymmetric", "DH", "vec.txt"), load_nist_vectors
+ ),
+ )
def test_dh_vectors(self, backend, vector):
- parameters = dh.DHParameterNumbers(int(vector["p"]),
- int(vector["g"]))
+ if (
+ backend._fips_enabled
+ and int(vector["p"]) < backend._fips_dh_min_modulus
+ ):
+ pytest.skip("modulus too small for FIPS mode")
+
+ if int(vector["p"]).bit_length() < 512:
+ pytest.skip("DH keys less than 512 bits are unsupported")
+
+ parameters = dh.DHParameterNumbers(int(vector["p"]), int(vector["g"]))
public = dh.DHPublicNumbers(int(vector["y"]), parameters)
private = dh.DHPrivateNumbers(int(vector["x"]), public)
key = private.private_key(backend)
symkey = key.exchange(public.public_key(backend))
- assert int_from_bytes(symkey, 'big') == int(vector["k"], 16)
+ assert int_from_bytes(symkey, "big") == int(vector["k"], 16)
+ @pytest.mark.skip_fips(reason="non-FIPS parameters")
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
- os.path.join("asymmetric", "DH", "RFC5114.txt"),
- load_nist_vectors))
+ os.path.join("asymmetric", "DH", "RFC5114.txt"), load_nist_vectors
+ ),
+ )
def test_dh_vectors_with_q(self, backend, vector):
- parameters = dh.DHParameterNumbers(int(vector["p"], 16),
- int(vector["g"], 16),
- int(vector["q"], 16))
+ parameters = dh.DHParameterNumbers(
+ int(vector["p"], 16), int(vector["g"], 16), int(vector["q"], 16)
+ )
public1 = dh.DHPublicNumbers(int(vector["ystatcavs"], 16), parameters)
private1 = dh.DHPrivateNumbers(int(vector["xstatcavs"], 16), public1)
public2 = dh.DHPublicNumbers(int(vector["ystatiut"], 16), parameters)
@@ -390,35 +444,28 @@ class TestDH(object):
symkey1 = key1.exchange(public2.public_key(backend))
symkey2 = key2.exchange(public1.public_key(backend))
- assert int_from_bytes(symkey1, 'big') == int(vector["z"], 16)
- assert int_from_bytes(symkey2, 'big') == int(vector["z"], 16)
+ assert int_from_bytes(symkey1, "big") == int(vector["z"], 16)
+ assert int_from_bytes(symkey2, "big") == int(vector["z"], 16)
@pytest.mark.requires_backend_interface(interface=DHBackend)
@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
@pytest.mark.requires_backend_interface(interface=DERSerializationBackend)
class TestDHPrivateKeySerialization(object):
-
@pytest.mark.parametrize(
("encoding", "loader_func"),
[
- [
- serialization.Encoding.PEM,
- serialization.load_pem_private_key
- ],
- [
- serialization.Encoding.DER,
- serialization.load_der_private_key
- ],
- ]
+ [serialization.Encoding.PEM, serialization.load_pem_private_key],
+ [serialization.Encoding.DER, serialization.load_der_private_key],
+ ],
)
- def test_private_bytes_unencrypted(self, backend, encoding,
- loader_func):
- parameters = dh.generate_parameters(2, 512, backend)
+ def test_private_bytes_unencrypted(self, backend, encoding, loader_func):
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key()
serialized = key.private_bytes(
- encoding, serialization.PrivateFormat.PKCS8,
- serialization.NoEncryption()
+ encoding,
+ serialization.PrivateFormat.PKCS8,
+ serialization.NoEncryption(),
)
loaded_key = loader_func(serialized, None, backend)
loaded_priv_num = loaded_key.private_numbers()
@@ -432,14 +479,15 @@ class TestDHPrivateKeySerialization(object):
(serialization.Encoding.DER, serialization.PrivateFormat.Raw),
(serialization.Encoding.Raw, serialization.PrivateFormat.Raw),
(serialization.Encoding.X962, serialization.PrivateFormat.PKCS8),
- ]
+ ],
)
def test_private_bytes_rejects_invalid(self, encoding, fmt, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key()
with pytest.raises(ValueError):
key.private_bytes(encoding, fmt, serialization.NoEncryption())
+ @pytest.mark.skip_fips(reason="non-FIPS parameters")
@pytest.mark.parametrize(
("key_path", "loader_func", "encoding", "is_dhx"),
[
@@ -448,38 +496,43 @@ class TestDHPrivateKeySerialization(object):
serialization.load_pem_private_key,
serialization.Encoding.PEM,
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhkey.der"),
serialization.load_der_private_key,
serialization.Encoding.DER,
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.pem"),
serialization.load_pem_private_key,
serialization.Encoding.PEM,
True,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.der"),
serialization.load_der_private_key,
serialization.Encoding.DER,
True,
- )
- ]
+ ),
+ ],
)
- def test_private_bytes_match(self, key_path, loader_func,
- encoding, is_dhx, backend):
+ def test_private_bytes_match(
+ self, key_path, loader_func, encoding, is_dhx, backend
+ ):
_skip_dhx_unsupported(backend, is_dhx)
key_bytes = load_vectors_from_file(
- key_path,
- lambda pemfile: pemfile.read(), mode="rb"
+ key_path, lambda pemfile: pemfile.read(), mode="rb"
)
key = loader_func(key_bytes, None, backend)
serialized = key.private_bytes(
- encoding, serialization.PrivateFormat.PKCS8,
- serialization.NoEncryption()
+ encoding,
+ serialization.PrivateFormat.PKCS8,
+ serialization.NoEncryption(),
)
assert serialized == key_bytes
+ @pytest.mark.skip_fips(reason="non-FIPS parameters")
@pytest.mark.parametrize(
("key_path", "loader_func", "vec_path", "is_dhx"),
[
@@ -488,30 +541,33 @@ class TestDHPrivateKeySerialization(object):
serialization.load_pem_private_key,
os.path.join("asymmetric", "DH", "dhkey.txt"),
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhkey.der"),
serialization.load_der_private_key,
os.path.join("asymmetric", "DH", "dhkey.txt"),
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.pem"),
serialization.load_pem_private_key,
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
True,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.der"),
serialization.load_der_private_key,
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
True,
- )
- ]
+ ),
+ ],
)
- def test_private_bytes_values(self, key_path, loader_func,
- vec_path, is_dhx, backend):
+ def test_private_bytes_values(
+ self, key_path, loader_func, vec_path, is_dhx, backend
+ ):
_skip_dhx_unsupported(backend, is_dhx)
key_bytes = load_vectors_from_file(
- key_path,
- lambda pemfile: pemfile.read(), mode="rb"
+ key_path, lambda pemfile: pemfile.read(), mode="rb"
)
vec = load_vectors_from_file(vec_path, load_nist_vectors)[0]
key = loader_func(key_bytes, None, backend)
@@ -519,63 +575,66 @@ class TestDHPrivateKeySerialization(object):
assert private_numbers.x == int(vec["x"], 16)
assert private_numbers.public_numbers.y == int(vec["y"], 16)
assert private_numbers.public_numbers.parameter_numbers.g == int(
- vec["g"], 16)
+ vec["g"], 16
+ )
assert private_numbers.public_numbers.parameter_numbers.p == int(
- vec["p"], 16)
+ vec["p"], 16
+ )
if "q" in vec:
assert private_numbers.public_numbers.parameter_numbers.q == int(
- vec["q"], 16)
+ vec["q"], 16
+ )
else:
assert private_numbers.public_numbers.parameter_numbers.q is None
def test_private_bytes_traditional_openssl_invalid(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key()
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_private_bytes_invalid_encoding(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key()
with pytest.raises(TypeError):
key.private_bytes(
"notencoding",
serialization.PrivateFormat.PKCS8,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_private_bytes_invalid_format(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key()
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.PEM,
"invalidformat",
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_private_bytes_invalid_encryption_algorithm(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key()
with pytest.raises(TypeError):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
- "notanencalg"
+ "notanencalg",
)
def test_private_bytes_unsupported_encryption_type(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key()
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
- DummyKeySerializationEncryption()
+ DummyKeySerializationEncryption(),
)
@@ -583,23 +642,15 @@ class TestDHPrivateKeySerialization(object):
@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
@pytest.mark.requires_backend_interface(interface=DERSerializationBackend)
class TestDHPublicKeySerialization(object):
-
@pytest.mark.parametrize(
("encoding", "loader_func"),
[
- [
- serialization.Encoding.PEM,
- serialization.load_pem_public_key
- ],
- [
- serialization.Encoding.DER,
- serialization.load_der_public_key
- ],
- ]
+ [serialization.Encoding.PEM, serialization.load_pem_public_key],
+ [serialization.Encoding.DER, serialization.load_der_public_key],
+ ],
)
- def test_public_bytes(self, backend, encoding,
- loader_func):
- parameters = dh.generate_parameters(2, 512, backend)
+ def test_public_bytes(self, backend, encoding, loader_func):
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key().public_key()
serialized = key.public_bytes(
encoding, serialization.PublicFormat.SubjectPublicKeyInfo
@@ -617,30 +668,33 @@ class TestDHPublicKeySerialization(object):
serialization.load_pem_public_key,
serialization.Encoding.PEM,
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhpub.der"),
serialization.load_der_public_key,
serialization.Encoding.DER,
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.pem"),
serialization.load_pem_public_key,
serialization.Encoding.PEM,
True,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.der"),
serialization.load_der_public_key,
serialization.Encoding.DER,
True,
- )
- ]
+ ),
+ ],
)
- def test_public_bytes_match(self, key_path, loader_func,
- encoding, is_dhx, backend):
+ def test_public_bytes_match(
+ self, key_path, loader_func, encoding, is_dhx, backend
+ ):
_skip_dhx_unsupported(backend, is_dhx)
key_bytes = load_vectors_from_file(
- key_path,
- lambda pemfile: pemfile.read(), mode="rb"
+ key_path, lambda pemfile: pemfile.read(), mode="rb"
)
pub_key = loader_func(key_bytes, backend)
serialized = pub_key.public_bytes(
@@ -657,30 +711,33 @@ class TestDHPublicKeySerialization(object):
serialization.load_pem_public_key,
os.path.join("asymmetric", "DH", "dhkey.txt"),
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhpub.der"),
serialization.load_der_public_key,
os.path.join("asymmetric", "DH", "dhkey.txt"),
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.pem"),
serialization.load_pem_public_key,
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
True,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhpub_rfc5114_2.der"),
serialization.load_der_public_key,
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
True,
- )
- ]
+ ),
+ ],
)
- def test_public_bytes_values(self, key_path, loader_func,
- vec_path, is_dhx, backend):
+ def test_public_bytes_values(
+ self, key_path, loader_func, vec_path, is_dhx, backend
+ ):
_skip_dhx_unsupported(backend, is_dhx)
key_bytes = load_vectors_from_file(
- key_path,
- lambda pemfile: pemfile.read(), mode="rb"
+ key_path, lambda pemfile: pemfile.read(), mode="rb"
)
vec = load_vectors_from_file(vec_path, load_nist_vectors)[0]
pub_key = loader_func(key_bytes, backend)
@@ -694,16 +751,15 @@ class TestDHPublicKeySerialization(object):
assert public_numbers.parameter_numbers.q is None
def test_public_bytes_invalid_encoding(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key().public_key()
with pytest.raises(TypeError):
key.public_bytes(
- "notencoding",
- serialization.PublicFormat.SubjectPublicKeyInfo
+ "notencoding", serialization.PublicFormat.SubjectPublicKeyInfo
)
def test_public_bytes_pkcs1_unsupported(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key().public_key()
with pytest.raises(ValueError):
key.public_bytes(
@@ -715,23 +771,15 @@ class TestDHPublicKeySerialization(object):
@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
@pytest.mark.requires_backend_interface(interface=DERSerializationBackend)
class TestDHParameterSerialization(object):
-
@pytest.mark.parametrize(
("encoding", "loader_func"),
[
- [
- serialization.Encoding.PEM,
- serialization.load_pem_parameters
- ],
- [
- serialization.Encoding.DER,
- serialization.load_der_parameters
- ],
- ]
+ [serialization.Encoding.PEM, serialization.load_pem_parameters],
+ [serialization.Encoding.DER, serialization.load_der_parameters],
+ ],
)
- def test_parameter_bytes(self, backend, encoding,
- loader_func):
- parameters = dh.generate_parameters(2, 512, backend)
+ def test_parameter_bytes(self, backend, encoding, loader_func):
+ parameters = FFDH3072_P.parameters(backend)
serialized = parameters.parameter_bytes(
encoding, serialization.ParameterFormat.PKCS3
)
@@ -747,30 +795,33 @@ class TestDHParameterSerialization(object):
serialization.load_pem_parameters,
serialization.Encoding.PEM,
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhp.der"),
serialization.load_der_parameters,
serialization.Encoding.DER,
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhp_rfc5114_2.pem"),
serialization.load_pem_parameters,
serialization.Encoding.PEM,
True,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhp_rfc5114_2.der"),
serialization.load_der_parameters,
serialization.Encoding.DER,
True,
- )
- ]
+ ),
+ ],
)
- def test_parameter_bytes_match(self, param_path, loader_func,
- encoding, backend, is_dhx):
+ def test_parameter_bytes_match(
+ self, param_path, loader_func, encoding, backend, is_dhx
+ ):
_skip_dhx_unsupported(backend, is_dhx)
param_bytes = load_vectors_from_file(
- param_path,
- lambda pemfile: pemfile.read(), mode="rb"
+ param_path, lambda pemfile: pemfile.read(), mode="rb"
)
parameters = loader_func(param_bytes, backend)
serialized = parameters.parameter_bytes(
@@ -787,30 +838,33 @@ class TestDHParameterSerialization(object):
serialization.load_pem_parameters,
os.path.join("asymmetric", "DH", "dhkey.txt"),
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhp.der"),
serialization.load_der_parameters,
os.path.join("asymmetric", "DH", "dhkey.txt"),
False,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhp_rfc5114_2.pem"),
serialization.load_pem_parameters,
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
True,
- ), (
+ ),
+ (
os.path.join("asymmetric", "DH", "dhp_rfc5114_2.der"),
serialization.load_der_parameters,
os.path.join("asymmetric", "DH", "dhkey_rfc5114_2.txt"),
True,
- )
- ]
+ ),
+ ],
)
- def test_public_bytes_values(self, param_path, loader_func,
- vec_path, backend, is_dhx):
+ def test_public_bytes_values(
+ self, param_path, loader_func, vec_path, backend, is_dhx
+ ):
_skip_dhx_unsupported(backend, is_dhx)
key_bytes = load_vectors_from_file(
- param_path,
- lambda pemfile: pemfile.read(), mode="rb"
+ param_path, lambda pemfile: pemfile.read(), mode="rb"
)
vec = load_vectors_from_file(vec_path, load_nist_vectors)[0]
parameters = loader_func(key_bytes, backend)
@@ -827,49 +881,48 @@ class TestDHParameterSerialization(object):
[
(
serialization.Encoding.Raw,
- serialization.PublicFormat.SubjectPublicKeyInfo
+ serialization.PublicFormat.SubjectPublicKeyInfo,
),
(serialization.Encoding.Raw, serialization.PublicFormat.PKCS1),
- ] + list(itertools.product(
- [
- serialization.Encoding.Raw,
- serialization.Encoding.X962,
- serialization.Encoding.PEM,
- serialization.Encoding.DER
- ],
- [
- serialization.PublicFormat.Raw,
- serialization.PublicFormat.UncompressedPoint,
- serialization.PublicFormat.CompressedPoint
- ]
- ))
+ ]
+ + list(
+ itertools.product(
+ [
+ serialization.Encoding.Raw,
+ serialization.Encoding.X962,
+ serialization.Encoding.PEM,
+ serialization.Encoding.DER,
+ ],
+ [
+ serialization.PublicFormat.Raw,
+ serialization.PublicFormat.UncompressedPoint,
+ serialization.PublicFormat.CompressedPoint,
+ ],
+ )
+ ),
)
def test_public_bytes_rejects_invalid(self, encoding, fmt, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
key = parameters.generate_private_key().public_key()
with pytest.raises(ValueError):
key.public_bytes(encoding, fmt)
def test_parameter_bytes_invalid_encoding(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
with pytest.raises(TypeError):
parameters.parameter_bytes(
- "notencoding",
- serialization.ParameterFormat.PKCS3
+ "notencoding", serialization.ParameterFormat.PKCS3
)
def test_parameter_bytes_invalid_format(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
with pytest.raises(ValueError):
- parameters.parameter_bytes(
- serialization.Encoding.PEM,
- "notformat"
- )
+ parameters.parameter_bytes(serialization.Encoding.PEM, "notformat")
def test_parameter_bytes_openssh_unsupported(self, backend):
- parameters = dh.generate_parameters(2, 512, backend)
+ parameters = FFDH3072_P.parameters(backend)
with pytest.raises(TypeError):
parameters.parameter_bytes(
serialization.Encoding.OpenSSH,
- serialization.ParameterFormat.PKCS3
+ serialization.ParameterFormat.PKCS3,
)
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index efd2239c1..bda275064 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -11,32 +11,33 @@ import pytest
from cryptography.exceptions import AlreadyFinalized, InvalidSignature
from cryptography.hazmat.backends.interfaces import (
- DSABackend, PEMSerializationBackend
+ DSABackend,
+ PEMSerializationBackend,
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import dsa
from cryptography.hazmat.primitives.asymmetric.utils import (
- Prehashed, encode_dss_signature
+ Prehashed,
+ encode_dss_signature,
)
from cryptography.utils import CryptographyDeprecationWarning
-from .fixtures_dsa import (
- DSA_KEY_1024, DSA_KEY_2048, DSA_KEY_3072
-)
+from .fixtures_dsa import DSA_KEY_1024, DSA_KEY_2048, DSA_KEY_3072
+from .utils import skip_fips_traditional_openssl
from ...doubles import DummyHashAlgorithm, DummyKeySerializationEncryption
from ...utils import (
- load_fips_dsa_key_pair_vectors, load_fips_dsa_sig_vectors,
+ load_fips_dsa_key_pair_vectors,
+ load_fips_dsa_sig_vectors,
load_vectors_from_file,
)
def _skip_if_dsa_not_supported(backend, algorithm, p, q, g):
- if (
- not backend.dsa_parameters_supported(p, q, g) or
- not backend.dsa_hash_supported(algorithm)
- ):
+ if not backend.dsa_parameters_supported(
+ p, q, g
+ ) or not backend.dsa_hash_supported(algorithm):
pytest.skip(
- "{0} does not support the provided parameters".format(backend)
+ "{} does not support the provided parameters".format(backend)
)
@@ -49,7 +50,7 @@ def test_skip_if_dsa_not_supported(backend):
@pytest.mark.requires_backend_interface(interface=DSABackend)
class TestDSA(object):
def test_generate_dsa_parameters(self, backend):
- parameters = dsa.generate_parameters(1024, backend)
+ parameters = dsa.generate_parameters(2048, backend)
assert isinstance(parameters, dsa.DSAParameters)
def test_generate_invalid_dsa_parameters(self, backend):
@@ -59,16 +60,18 @@ class TestDSA(object):
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
- os.path.join(
- "asymmetric", "DSA", "FIPS_186-3", "KeyPair.rsp"),
- load_fips_dsa_key_pair_vectors
- )
+ os.path.join("asymmetric", "DSA", "FIPS_186-3", "KeyPair.rsp"),
+ load_fips_dsa_key_pair_vectors,
+ ),
)
def test_generate_dsa_keys(self, vector, backend):
+ if (
+ backend._fips_enabled
+ and vector["p"] < backend._fips_dsa_min_modulus
+ ):
+ pytest.skip("Small modulus blocked in FIPS mode")
parameters = dsa.DSAParameterNumbers(
- p=vector['p'],
- q=vector['q'],
- g=vector['g']
+ p=vector["p"], q=vector["q"], g=vector["g"]
).parameters(backend)
skey = parameters.generate_private_key()
numbers = skey.private_numbers()
@@ -79,10 +82,10 @@ class TestDSA(object):
assert parameter_numbers.p == skey_parameters.p
assert parameter_numbers.q == skey_parameters.q
assert parameter_numbers.g == skey_parameters.g
- assert skey_parameters.p == vector['p']
- assert skey_parameters.q == vector['q']
- assert skey_parameters.g == vector['g']
- assert skey.key_size == vector['p'].bit_length()
+ assert skey_parameters.p == vector["p"]
+ assert skey_parameters.q == vector["q"]
+ assert skey_parameters.g == vector["g"]
+ assert skey.key_size == vector["p"].bit_length()
assert pkey.key_size == skey.key_size
public_numbers = pkey.public_numbers()
assert numbers.public_numbers.y == public_numbers.y
@@ -91,7 +94,7 @@ class TestDSA(object):
)
def test_generate_dsa_private_key_and_parameters(self, backend):
- skey = dsa.generate_private_key(1024, backend)
+ skey = dsa.generate_private_key(2048, backend)
assert skey
numbers = skey.private_numbers()
skey_parameters = numbers.public_numbers.parameter_numbers
@@ -130,7 +133,7 @@ class TestDSA(object):
(
DSA_KEY_2048.public_numbers.parameter_numbers.p,
2 ** 250,
- DSA_KEY_2048.public_numbers.parameter_numbers.g
+ DSA_KEY_2048.public_numbers.parameter_numbers.g,
),
(
DSA_KEY_3072.public_numbers.parameter_numbers.p,
@@ -140,19 +143,19 @@ class TestDSA(object):
(
DSA_KEY_1024.public_numbers.parameter_numbers.p,
DSA_KEY_1024.public_numbers.parameter_numbers.q,
- 0
+ 0,
),
(
DSA_KEY_1024.public_numbers.parameter_numbers.p,
DSA_KEY_1024.public_numbers.parameter_numbers.q,
- 1
+ 1,
),
(
DSA_KEY_1024.public_numbers.parameter_numbers.p,
DSA_KEY_1024.public_numbers.parameter_numbers.q,
- 2 ** 1200
+ 2 ** 1200,
),
- ]
+ ],
)
def test_invalid_parameters_values(self, p, q, g, backend):
with pytest.raises(ValueError):
@@ -264,17 +267,18 @@ class TestDSA(object):
DSA_KEY_1024.public_numbers.parameter_numbers.q,
DSA_KEY_1024.public_numbers.parameter_numbers.g,
2 ** 100,
- DSA_KEY_1024.x
+ DSA_KEY_1024.x,
),
- ]
+ ],
)
def test_invalid_dsa_private_key_arguments(self, p, q, g, y, x, backend):
with pytest.raises(ValueError):
dsa.DSAPrivateNumbers(
public_numbers=dsa.DSAPublicNumbers(
parameter_numbers=dsa.DSAParameterNumbers(p=p, q=q, g=g),
- y=y
- ), x=x
+ y=y,
+ ),
+ x=x,
).private_key(backend)
@pytest.mark.parametrize(
@@ -340,72 +344,95 @@ class TestDSA(object):
2 ** 1200,
DSA_KEY_1024.public_numbers.y,
),
- ]
+ ],
)
def test_invalid_dsa_public_key_arguments(self, p, q, g, y, backend):
with pytest.raises(ValueError):
dsa.DSAPublicNumbers(
- parameter_numbers=dsa.DSAParameterNumbers(p=p, q=q, g=g),
- y=y
+ parameter_numbers=dsa.DSAParameterNumbers(p=p, q=q, g=g), y=y
).public_key(backend)
+ def test_large_p(self, backend):
+ key = load_vectors_from_file(
+ os.path.join("asymmetric", "PEM_Serialization", "dsa_4096.pem"),
+ lambda pemfile: serialization.load_pem_private_key(
+ pemfile.read(), None, backend
+ ),
+ mode="rb",
+ )
+ pn = key.private_numbers()
+ assert pn.public_numbers.parameter_numbers.p.bit_length() == 4096
+ # Turn it back into a key to confirm that values this large pass
+ # verification
+ dsa.DSAPrivateNumbers(
+ public_numbers=dsa.DSAPublicNumbers(
+ parameter_numbers=dsa.DSAParameterNumbers(
+ p=pn.public_numbers.parameter_numbers.p,
+ q=pn.public_numbers.parameter_numbers.q,
+ g=pn.public_numbers.parameter_numbers.g,
+ ),
+ y=pn.public_numbers.y,
+ ),
+ x=pn.x,
+ ).private_key(backend)
+
@pytest.mark.requires_backend_interface(interface=DSABackend)
class TestDSAVerification(object):
_algorithms_dict = {
- 'SHA1': hashes.SHA1,
- 'SHA224': hashes.SHA224,
- 'SHA256': hashes.SHA256,
- 'SHA384': hashes.SHA384,
- 'SHA512': hashes.SHA512
+ "SHA1": hashes.SHA1,
+ "SHA224": hashes.SHA224,
+ "SHA256": hashes.SHA256,
+ "SHA384": hashes.SHA384,
+ "SHA512": hashes.SHA512,
}
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
- os.path.join(
- "asymmetric", "DSA", "FIPS_186-3", "SigVer.rsp"),
- load_fips_dsa_sig_vectors
- )
+ os.path.join("asymmetric", "DSA", "FIPS_186-3", "SigVer.rsp"),
+ load_fips_dsa_sig_vectors,
+ ),
)
def test_dsa_verification(self, vector, backend):
- digest_algorithm = vector['digest_algorithm'].replace("-", "")
+ digest_algorithm = vector["digest_algorithm"].replace("-", "")
algorithm = self._algorithms_dict[digest_algorithm]
_skip_if_dsa_not_supported(
- backend, algorithm, vector['p'], vector['q'], vector['g']
+ backend, algorithm, vector["p"], vector["q"], vector["g"]
)
public_key = dsa.DSAPublicNumbers(
parameter_numbers=dsa.DSAParameterNumbers(
- vector['p'], vector['q'], vector['g']
+ vector["p"], vector["q"], vector["g"]
),
- y=vector['y']
+ y=vector["y"],
).public_key(backend)
- sig = encode_dss_signature(vector['r'], vector['s'])
+ sig = encode_dss_signature(vector["r"], vector["s"])
- if vector['result'] == "F":
+ if vector["result"] == "F":
with pytest.raises(InvalidSignature):
- public_key.verify(sig, vector['msg'], algorithm())
+ public_key.verify(sig, vector["msg"], algorithm())
else:
- public_key.verify(sig, vector['msg'], algorithm())
+ public_key.verify(sig, vector["msg"], algorithm())
def test_dsa_verify_invalid_asn1(self, backend):
public_key = DSA_KEY_1024.public_numbers.public_key(backend)
with pytest.raises(InvalidSignature):
- public_key.verify(b'fakesig', b'fakemsg', hashes.SHA1())
+ public_key.verify(b"fakesig", b"fakemsg", hashes.SHA1())
def test_signature_not_bytes(self, backend):
public_key = DSA_KEY_1024.public_numbers.public_key(backend)
- with pytest.raises(TypeError), \
- pytest.warns(CryptographyDeprecationWarning):
+ with pytest.raises(TypeError), pytest.warns(
+ CryptographyDeprecationWarning
+ ):
public_key.verifier(1234, hashes.SHA1())
def test_use_after_finalize(self, backend):
public_key = DSA_KEY_1024.public_numbers.public_key(backend)
with pytest.warns(CryptographyDeprecationWarning):
- verifier = public_key.verifier(b'fakesig', hashes.SHA1())
- verifier.update(b'irrelevant')
+ verifier = public_key.verifier(b"fakesig", hashes.SHA1())
+ verifier.update(b"irrelevant")
with pytest.raises(InvalidSignature):
verifier.verify()
with pytest.raises(AlreadyFinalized):
@@ -445,57 +472,57 @@ class TestDSAVerification(object):
def test_prehashed_unsupported_in_signer_ctx(self, backend):
private_key = DSA_KEY_1024.private_key(backend)
- with pytest.raises(TypeError), \
- pytest.warns(CryptographyDeprecationWarning):
+ with pytest.raises(TypeError), pytest.warns(
+ CryptographyDeprecationWarning
+ ):
private_key.signer(Prehashed(hashes.SHA1()))
def test_prehashed_unsupported_in_verifier_ctx(self, backend):
public_key = DSA_KEY_1024.private_key(backend).public_key()
- with pytest.raises(TypeError), \
- pytest.warns(CryptographyDeprecationWarning):
- public_key.verifier(
- b"0" * 64, Prehashed(hashes.SHA1())
- )
+ with pytest.raises(TypeError), pytest.warns(
+ CryptographyDeprecationWarning
+ ):
+ public_key.verifier(b"0" * 64, Prehashed(hashes.SHA1()))
@pytest.mark.requires_backend_interface(interface=DSABackend)
class TestDSASignature(object):
_algorithms_dict = {
- 'SHA1': hashes.SHA1,
- 'SHA224': hashes.SHA224,
- 'SHA256': hashes.SHA256,
- 'SHA384': hashes.SHA384,
- 'SHA512': hashes.SHA512}
+ "SHA1": hashes.SHA1,
+ "SHA224": hashes.SHA224,
+ "SHA256": hashes.SHA256,
+ "SHA384": hashes.SHA384,
+ "SHA512": hashes.SHA512,
+ }
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
- os.path.join(
- "asymmetric", "DSA", "FIPS_186-3", "SigGen.txt"),
- load_fips_dsa_sig_vectors
- )
+ os.path.join("asymmetric", "DSA", "FIPS_186-3", "SigGen.txt"),
+ load_fips_dsa_sig_vectors,
+ ),
)
def test_dsa_signing(self, vector, backend):
- digest_algorithm = vector['digest_algorithm'].replace("-", "")
+ digest_algorithm = vector["digest_algorithm"].replace("-", "")
algorithm = self._algorithms_dict[digest_algorithm]
_skip_if_dsa_not_supported(
- backend, algorithm, vector['p'], vector['q'], vector['g']
+ backend, algorithm, vector["p"], vector["q"], vector["g"]
)
private_key = dsa.DSAPrivateNumbers(
public_numbers=dsa.DSAPublicNumbers(
parameter_numbers=dsa.DSAParameterNumbers(
- vector['p'], vector['q'], vector['g']
+ vector["p"], vector["q"], vector["g"]
),
- y=vector['y']
+ y=vector["y"],
),
- x=vector['x']
+ x=vector["x"],
).private_key(backend)
- signature = private_key.sign(vector['msg'], algorithm())
+ signature = private_key.sign(vector["msg"], algorithm())
assert signature
- private_key.public_key().verify(signature, vector['msg'], algorithm())
+ private_key.public_key().verify(signature, vector["msg"], algorithm())
def test_use_after_finalize(self, backend):
private_key = DSA_KEY_1024.private_key(backend)
@@ -558,8 +585,7 @@ class TestDSANumbers(object):
def test_dsa_public_numbers(self):
parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3)
public_numbers = dsa.DSAPublicNumbers(
- y=4,
- parameter_numbers=parameter_numbers
+ y=4, parameter_numbers=parameter_numbers
)
assert public_numbers.y == 4
assert public_numbers.parameter_numbers == parameter_numbers
@@ -575,12 +601,10 @@ class TestDSANumbers(object):
def test_dsa_private_numbers(self):
parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3)
public_numbers = dsa.DSAPublicNumbers(
- y=4,
- parameter_numbers=parameter_numbers
+ y=4, parameter_numbers=parameter_numbers
)
private_numbers = dsa.DSAPrivateNumbers(
- x=5,
- public_numbers=public_numbers
+ x=5, public_numbers=public_numbers
)
assert private_numbers.x == 5
assert private_numbers.public_numbers == public_numbers
@@ -588,8 +612,7 @@ class TestDSANumbers(object):
def test_dsa_private_numbers_invalid_types(self):
parameter_numbers = dsa.DSAParameterNumbers(p=1, q=2, g=3)
public_numbers = dsa.DSAPublicNumbers(
- y=4,
- parameter_numbers=parameter_numbers
+ y=4, parameter_numbers=parameter_numbers
)
with pytest.raises(TypeError):
dsa.DSAPrivateNumbers(x=4, public_numbers=None)
@@ -604,8 +627,7 @@ class TestDSANumbers(object):
)
public_numbers = dsa.DSAPublicNumbers(
- y=4,
- parameter_numbers=parameter_numbers
+ y=4, parameter_numbers=parameter_numbers
)
assert repr(public_numbers) == (
"<DSAPublicNumbers(y=4, parameter_numbers=<DSAParameterNumbers(p=1"
@@ -641,38 +663,26 @@ class TestDSANumberEquality(object):
pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
priv = dsa.DSAPrivateNumbers(1, pub)
assert priv == dsa.DSAPrivateNumbers(
- 1, dsa.DSAPublicNumbers(
- 1, dsa.DSAParameterNumbers(1, 2, 3)
- )
+ 1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
)
def test_private_numbers_ne(self):
pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
priv = dsa.DSAPrivateNumbers(1, pub)
assert priv != dsa.DSAPrivateNumbers(
- 2, dsa.DSAPublicNumbers(
- 1, dsa.DSAParameterNumbers(1, 2, 3)
- )
+ 2, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))
)
assert priv != dsa.DSAPrivateNumbers(
- 1, dsa.DSAPublicNumbers(
- 2, dsa.DSAParameterNumbers(1, 2, 3)
- )
+ 1, dsa.DSAPublicNumbers(2, dsa.DSAParameterNumbers(1, 2, 3))
)
assert priv != dsa.DSAPrivateNumbers(
- 1, dsa.DSAPublicNumbers(
- 1, dsa.DSAParameterNumbers(2, 2, 3)
- )
+ 1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(2, 2, 3))
)
assert priv != dsa.DSAPrivateNumbers(
- 1, dsa.DSAPublicNumbers(
- 1, dsa.DSAParameterNumbers(1, 3, 3)
- )
+ 1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 3, 3))
)
assert priv != dsa.DSAPrivateNumbers(
- 1, dsa.DSAPublicNumbers(
- 1, dsa.DSAParameterNumbers(1, 2, 4)
- )
+ 1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 4))
)
assert priv != object()
@@ -685,26 +695,27 @@ class TestDSASerialization(object):
itertools.product(
[
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.PrivateFormat.PKCS8
+ serialization.PrivateFormat.PKCS8,
],
[
b"s",
b"longerpassword",
b"!*$&(@#$*&($T@%_somesymbols",
b"\x01" * 1000,
- ]
- )
+ ],
+ ),
)
def test_private_bytes_encrypted_pem(self, backend, fmt, password):
+ skip_fips_traditional_openssl(backend, fmt)
key_bytes = load_vectors_from_file(
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
- lambda pemfile: pemfile.read().encode()
+ lambda pemfile: pemfile.read().encode(),
)
key = serialization.load_pem_private_key(key_bytes, None, backend)
serialized = key.private_bytes(
serialization.Encoding.PEM,
fmt,
- serialization.BestAvailableEncryption(password)
+ serialization.BestAvailableEncryption(password),
)
loaded_key = serialization.load_pem_private_key(
serialized, password, backend
@@ -720,7 +731,7 @@ class TestDSASerialization(object):
(serialization.Encoding.DER, serialization.PrivateFormat.Raw),
(serialization.Encoding.Raw, serialization.PrivateFormat.Raw),
(serialization.Encoding.X962, serialization.PrivateFormat.PKCS8),
- ]
+ ],
)
def test_private_bytes_rejects_invalid(self, encoding, fmt, backend):
key = DSA_KEY_1024.private_key(backend)
@@ -733,19 +744,19 @@ class TestDSASerialization(object):
[serialization.PrivateFormat.PKCS8, b"s"],
[serialization.PrivateFormat.PKCS8, b"longerpassword"],
[serialization.PrivateFormat.PKCS8, b"!*$&(@#$*&($T@%_somesymbol"],
- [serialization.PrivateFormat.PKCS8, b"\x01" * 1000]
- ]
+ [serialization.PrivateFormat.PKCS8, b"\x01" * 1000],
+ ],
)
def test_private_bytes_encrypted_der(self, backend, fmt, password):
key_bytes = load_vectors_from_file(
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
- lambda pemfile: pemfile.read().encode()
+ lambda pemfile: pemfile.read().encode(),
)
key = serialization.load_pem_private_key(key_bytes, None, backend)
serialized = key.private_bytes(
serialization.Encoding.DER,
fmt,
- serialization.BestAvailableEncryption(password)
+ serialization.BestAvailableEncryption(password),
)
loaded_key = serialization.load_der_private_key(
serialized, password, backend
@@ -760,27 +771,28 @@ class TestDSASerialization(object):
[
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
],
[
serialization.Encoding.DER,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
],
[
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
],
[
serialization.Encoding.DER,
serialization.PrivateFormat.PKCS8,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
],
- ]
+ ],
)
- def test_private_bytes_unencrypted(self, backend, encoding, fmt,
- loader_func):
+ def test_private_bytes_unencrypted(
+ self, backend, encoding, fmt, loader_func
+ ):
key = DSA_KEY_1024.private_key(backend)
serialized = key.private_bytes(
encoding, fmt, serialization.NoEncryption()
@@ -790,6 +802,9 @@ class TestDSASerialization(object):
priv_num = key.private_numbers()
assert loaded_priv_num == priv_num
+ @pytest.mark.skip_fips(
+ reason="Traditional OpenSSL key format is not supported in FIPS mode."
+ )
@pytest.mark.parametrize(
("key_path", "encoding", "loader_func"),
[
@@ -797,19 +812,19 @@ class TestDSASerialization(object):
os.path.join(
"asymmetric",
"Traditional_OpenSSL_Serialization",
- "dsa.1024.pem"
+ "dsa.1024.pem",
),
serialization.Encoding.PEM,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
],
[
os.path.join(
"asymmetric", "DER_Serialization", "dsa.1024.der"
),
serialization.Encoding.DER,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
],
- ]
+ ],
)
def test_private_bytes_traditional_openssl_unencrypted(
self, backend, key_path, encoding, loader_func
@@ -821,7 +836,7 @@ class TestDSASerialization(object):
serialized = key.private_bytes(
encoding,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
assert serialized == key_bytes
@@ -831,7 +846,7 @@ class TestDSASerialization(object):
key.private_bytes(
serialization.Encoding.DER,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.BestAvailableEncryption(b"password")
+ serialization.BestAvailableEncryption(b"password"),
)
def test_private_bytes_invalid_encoding(self, backend):
@@ -839,13 +854,13 @@ class TestDSASerialization(object):
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with pytest.raises(TypeError):
key.private_bytes(
"notencoding",
serialization.PrivateFormat.PKCS8,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_private_bytes_invalid_format(self, backend):
@@ -853,13 +868,13 @@ class TestDSASerialization(object):
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with pytest.raises(TypeError):
key.private_bytes(
serialization.Encoding.PEM,
"invalidformat",
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_private_bytes_invalid_encryption_algorithm(self, backend):
@@ -867,13 +882,13 @@ class TestDSASerialization(object):
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with pytest.raises(TypeError):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- "notanencalg"
+ "notanencalg",
)
def test_private_bytes_unsupported_encryption_type(self, backend):
@@ -881,13 +896,13 @@ class TestDSASerialization(object):
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- DummyKeySerializationEncryption()
+ DummyKeySerializationEncryption(),
)
@@ -901,32 +916,36 @@ class TestDSAPEMPublicKeySerialization(object):
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"),
serialization.load_pem_public_key,
serialization.Encoding.PEM,
- ), (
+ ),
+ (
os.path.join(
"asymmetric",
"DER_Serialization",
- "unenc-dsa-pkcs8.pub.der"
+ "unenc-dsa-pkcs8.pub.der",
),
serialization.load_der_public_key,
serialization.Encoding.DER,
- )
- ]
+ ),
+ ],
)
- def test_public_bytes_match(self, key_path, loader_func, encoding,
- backend):
+ def test_public_bytes_match(
+ self, key_path, loader_func, encoding, backend
+ ):
key_bytes = load_vectors_from_file(
key_path, lambda pemfile: pemfile.read(), mode="rb"
)
key = loader_func(key_bytes, backend)
serialized = key.public_bytes(
- encoding, serialization.PublicFormat.SubjectPublicKeyInfo,
+ encoding,
+ serialization.PublicFormat.SubjectPublicKeyInfo,
)
assert serialized == key_bytes
def test_public_bytes_openssh(self, backend):
key_bytes = load_vectors_from_file(
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"),
- lambda pemfile: pemfile.read(), mode="rb"
+ lambda pemfile: pemfile.read(),
+ mode="rb",
)
key = serialization.load_pem_public_key(key_bytes, backend)
@@ -950,8 +969,7 @@ class TestDSAPEMPublicKeySerialization(object):
key = DSA_KEY_2048.private_key(backend).public_key()
with pytest.raises(TypeError):
key.public_bytes(
- "notencoding",
- serialization.PublicFormat.SubjectPublicKeyInfo
+ "notencoding", serialization.PublicFormat.SubjectPublicKeyInfo
)
def test_public_bytes_invalid_format(self, backend):
@@ -971,22 +989,25 @@ class TestDSAPEMPublicKeySerialization(object):
[
(
serialization.Encoding.Raw,
- serialization.PublicFormat.SubjectPublicKeyInfo
+ serialization.PublicFormat.SubjectPublicKeyInfo,
),
(serialization.Encoding.Raw, serialization.PublicFormat.PKCS1),
- ] + list(itertools.product(
- [
- serialization.Encoding.Raw,
- serialization.Encoding.X962,
- serialization.Encoding.PEM,
- serialization.Encoding.DER
- ],
- [
- serialization.PublicFormat.Raw,
- serialization.PublicFormat.UncompressedPoint,
- serialization.PublicFormat.CompressedPoint
- ]
- ))
+ ]
+ + list(
+ itertools.product(
+ [
+ serialization.Encoding.Raw,
+ serialization.Encoding.X962,
+ serialization.Encoding.PEM,
+ serialization.Encoding.DER,
+ ],
+ [
+ serialization.PublicFormat.Raw,
+ serialization.PublicFormat.UncompressedPoint,
+ serialization.PublicFormat.CompressedPoint,
+ ],
+ )
+ ),
)
def test_public_bytes_rejects_invalid(self, encoding, fmt, backend):
key = DSA_KEY_2048.private_key(backend).public_key()
diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
index 7a6d6affb..8361306f7 100644
--- a/tests/hazmat/primitives/test_ec.py
+++ b/tests/hazmat/primitives/test_ec.py
@@ -11,23 +11,29 @@ from binascii import hexlify
import pytest
-from cryptography import exceptions, utils
+from cryptography import exceptions, utils, x509
from cryptography.hazmat.backends.interfaces import (
- EllipticCurveBackend, PEMSerializationBackend
+ EllipticCurveBackend,
+ PEMSerializationBackend,
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import (
- Prehashed, encode_dss_signature
+ Prehashed,
+ encode_dss_signature,
)
from cryptography.utils import CryptographyDeprecationWarning
from .fixtures_ec import EC_KEY_SECP384R1
+from .utils import skip_fips_traditional_openssl
from ...doubles import DummyKeySerializationEncryption
from ...utils import (
- load_fips_ecdsa_key_pair_vectors, load_fips_ecdsa_signing_vectors,
- load_kasvs_ecdh_vectors, load_nist_vectors, load_vectors_from_file,
- raises_unsupported_algorithm
+ load_fips_ecdsa_key_pair_vectors,
+ load_fips_ecdsa_signing_vectors,
+ load_kasvs_ecdh_vectors,
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
_HASH_TYPES = {
@@ -41,11 +47,10 @@ _HASH_TYPES = {
def _skip_ecdsa_vector(backend, curve_type, hash_type):
if not backend.elliptic_curve_signature_algorithm_supported(
- ec.ECDSA(hash_type()),
- curve_type()
+ ec.ECDSA(hash_type()), curve_type()
):
pytest.skip(
- "ECDSA not supported with this hash {0} and curve {1}".format(
+ "ECDSA not supported with this hash {} and curve {}.".format(
hash_type().name, curve_type().name
)
)
@@ -54,7 +59,7 @@ def _skip_ecdsa_vector(backend, curve_type, hash_type):
def _skip_curve_unsupported(backend, curve):
if not backend.elliptic_curve_supported(curve):
pytest.skip(
- "Curve {0} is not supported by this backend {1}".format(
+ "Curve {} is not supported by this backend {}".format(
curve.name, backend
)
)
@@ -65,12 +70,18 @@ def _skip_exchange_algorithm_unsupported(backend, algorithm, curve):
algorithm, curve
):
pytest.skip(
- "Exchange with {0} curve is not supported by {1}".format(
+ "Exchange with {} curve is not supported by {}".format(
curve.name, backend
)
)
+def test_get_curve_for_oid():
+ assert ec.get_curve_for_oid(ec.EllipticCurveOID.SECP256R1) == ec.SECP256R1
+ with pytest.raises(LookupError):
+ ec.get_curve_for_oid(x509.ObjectIdentifier("1.1.1.1"))
+
+
@utils.register_interface(ec.EllipticCurve)
class DummyCurve(object):
name = "dummy-curve"
@@ -120,10 +131,10 @@ def test_derive_private_key_errors(backend):
_skip_curve_unsupported(backend, curve)
with pytest.raises(TypeError):
- ec.derive_private_key('one', curve, backend)
+ ec.derive_private_key("one", curve, backend)
with pytest.raises(TypeError):
- ec.derive_private_key(10, 'five', backend)
+ ec.derive_private_key(10, "five", backend)
with pytest.raises(ValueError):
ec.derive_private_key(-7, curve, backend)
@@ -131,10 +142,7 @@ def test_derive_private_key_errors(backend):
def test_ec_numbers():
numbers = ec.EllipticCurvePrivateNumbers(
- 1,
- ec.EllipticCurvePublicNumbers(
- 2, 3, DummyCurve()
- )
+ 1, ec.EllipticCurvePublicNumbers(2, 3, DummyCurve())
)
assert numbers.private_value == 1
@@ -150,7 +158,7 @@ def test_ec_numbers():
(1, None, 3, DummyCurve()),
(1, 2, None, DummyCurve()),
(1, 2, 3, None),
- ]
+ ],
)
def test_invalid_ec_numbers_args(private_value, x, y, curve):
with pytest.raises(TypeError):
@@ -167,15 +175,13 @@ def test_invalid_private_numbers_public_numbers():
def test_encode_point():
# secp256r1 point
x = int(
- '233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec',
- 16
+ "233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec", 16
)
y = int(
- '3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e',
- 16
+ "3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e", 16
)
pn = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1())
- with pytest.warns(utils.DeprecatedIn25):
+ with pytest.warns(utils.PersistentlyDeprecated2019):
data = pn.encode_point()
assert data == binascii.unhexlify(
"04233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22ae"
@@ -194,12 +200,10 @@ def test_from_encoded_point():
ec.SECP256R1(), data
)
assert pn.x == int(
- '233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec',
- 16
+ "233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec", 16
)
assert pn.y == int(
- '3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e',
- 16
+ "3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e", 16
)
@@ -277,34 +281,35 @@ def test_ec_key_key_size(backend):
class TestECWithNumbers(object):
@pytest.mark.parametrize(
("vector", "hash_type"),
- list(itertools.product(
- load_vectors_from_file(
- os.path.join(
- "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp"),
- load_fips_ecdsa_key_pair_vectors
- ),
- _HASH_TYPES.values()
- ))
+ list(
+ itertools.product(
+ load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp"
+ ),
+ load_fips_ecdsa_key_pair_vectors,
+ ),
+ _HASH_TYPES.values(),
+ )
+ ),
)
def test_with_numbers(self, backend, vector, hash_type):
- curve_type = ec._CURVE_TYPES[vector['curve']]
+ curve_type = ec._CURVE_TYPES[vector["curve"]]
_skip_ecdsa_vector(backend, curve_type, hash_type)
key = ec.EllipticCurvePrivateNumbers(
- vector['d'],
+ vector["d"],
ec.EllipticCurvePublicNumbers(
- vector['x'],
- vector['y'],
- curve_type()
- )
+ vector["x"], vector["y"], curve_type()
+ ),
).private_key(backend)
assert key
priv_num = key.private_numbers()
- assert priv_num.private_value == vector['d']
- assert priv_num.public_numbers.x == vector['x']
- assert priv_num.public_numbers.y == vector['y']
+ assert priv_num.private_value == vector["d"]
+ assert priv_num.public_numbers.x == vector["x"]
+ assert priv_num.public_numbers.y == vector["y"]
assert curve_type().name == priv_num.public_numbers.curve.name
@@ -312,27 +317,28 @@ class TestECWithNumbers(object):
class TestECDSAVectors(object):
@pytest.mark.parametrize(
("vector", "hash_type"),
- list(itertools.product(
- load_vectors_from_file(
- os.path.join(
- "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp"),
- load_fips_ecdsa_key_pair_vectors
- ),
- _HASH_TYPES.values()
- ))
+ list(
+ itertools.product(
+ load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp"
+ ),
+ load_fips_ecdsa_key_pair_vectors,
+ ),
+ _HASH_TYPES.values(),
+ )
+ ),
)
def test_signing_with_example_keys(self, backend, vector, hash_type):
- curve_type = ec._CURVE_TYPES[vector['curve']]
+ curve_type = ec._CURVE_TYPES[vector["curve"]]
_skip_ecdsa_vector(backend, curve_type, hash_type)
key = ec.EllipticCurvePrivateNumbers(
- vector['d'],
+ vector["d"],
ec.EllipticCurvePublicNumbers(
- vector['x'],
- vector['y'],
- curve_type()
- )
+ vector["x"], vector["y"], curve_type()
+ ),
).private_key(backend)
assert key
@@ -349,9 +355,7 @@ class TestECDSAVectors(object):
verifier.update(b"YELLOW SUBMARINE")
verifier.verify()
- @pytest.mark.parametrize(
- "curve", ec._CURVE_TYPES.values()
- )
+ @pytest.mark.parametrize("curve", ec._CURVE_TYPES.values())
def test_generate_vector_curves(self, backend, curve):
_skip_curve_unsupported(backend, curve())
@@ -371,10 +375,12 @@ class TestECDSAVectors(object):
):
ec.generate_private_key(DummyCurve(), backend)
- assert backend.elliptic_curve_signature_algorithm_supported(
- ec.ECDSA(hashes.SHA256()),
- DummyCurve()
- ) is False
+ assert (
+ backend.elliptic_curve_signature_algorithm_supported(
+ ec.ECDSA(hashes.SHA256()), DummyCurve()
+ )
+ is False
+ )
def test_unknown_signature_algoritm(self, backend):
_skip_curve_unsupported(backend, ec.SECP192R1())
@@ -403,10 +409,12 @@ class TestECDSAVectors(object):
b"signature", b"data", DummySignatureAlgorithm()
)
- assert backend.elliptic_curve_signature_algorithm_supported(
- DummySignatureAlgorithm(),
- ec.SECP192R1()
- ) is False
+ assert (
+ backend.elliptic_curve_signature_algorithm_supported(
+ DummySignatureAlgorithm(), ec.SECP192R1()
+ )
+ is False
+ )
def test_load_invalid_ec_key_from_numbers(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
@@ -417,7 +425,7 @@ class TestECDSAVectors(object):
47250808410327023131573602008345894927686381772325561185532964,
1120253292479243545483756778742719537373113335231773536789915,
ec.SECP256R1(),
- )
+ ),
)
with pytest.raises(ValueError):
numbers.private_key(backend)
@@ -428,7 +436,7 @@ class TestECDSAVectors(object):
-4725080841032702313157360200834589492768638177232556118553296,
1120253292479243545483756778742719537373113335231773536789915,
ec.SECP256R1(),
- )
+ ),
)
with pytest.raises(ValueError):
numbers.private_key(backend)
@@ -439,7 +447,7 @@ class TestECDSAVectors(object):
47250808410327023131573602008345894927686381772325561185532964,
-1120253292479243545483756778742719537373113335231773536789915,
ec.SECP256R1(),
- )
+ ),
)
with pytest.raises(ValueError):
numbers.private_key(backend)
@@ -449,26 +457,38 @@ class TestECDSAVectors(object):
# Bad X coordinate
numbers = ec.EllipticCurvePublicNumbers(
- int("000003647356b91f8ace114c7247ecf4f4a622553fc025e04a178f179ef27"
+ int(
+ "000003647356b91f8ace114c7247ecf4f4a622553fc025e04a178f179ef27"
"9090c184af678a4c78f635483bdd8aa544851c6ef291c1f0d6a241ebfd145"
- "77d1d30d9903ce", 16),
- int("000001499bc7e079322ea0fcfbd6b40103fa6a1536c2257b182db0df4b369"
+ "77d1d30d9903ce",
+ 16,
+ ),
+ int(
+ "000001499bc7e079322ea0fcfbd6b40103fa6a1536c2257b182db0df4b369"
"6ec643adf100eb4f2025d1b873f82e5a475d6e4400ba777090eeb4563a115"
- "09e4c87319dc26", 16),
- ec.SECP521R1()
+ "09e4c87319dc26",
+ 16,
+ ),
+ ec.SECP521R1(),
)
with pytest.raises(ValueError):
numbers.public_key(backend)
# Bad Y coordinate
numbers = ec.EllipticCurvePublicNumbers(
- int("0000019aadc221cc0525118ab6d5aa1f64720603de0be128cbfea0b381ad8"
+ int(
+ "0000019aadc221cc0525118ab6d5aa1f64720603de0be128cbfea0b381ad8"
"02a2facc6370bb58cf88b3f0c692bc654ee19d6cad198f10d4b681b396f20"
- "d2e40603fa945b", 16),
- int("0000025da392803a320717a08d4cb3dea932039badff363b71bdb8064e726"
+ "d2e40603fa945b",
+ 16,
+ ),
+ int(
+ "0000025da392803a320717a08d4cb3dea932039badff363b71bdb8064e726"
"6c7f4f4b748d4d425347fc33e3885d34b750fa7fcd5691f4d90c89522ce33"
- "feff5db10088a5", 16),
- ec.SECP521R1()
+ "feff5db10088a5",
+ 16,
+ ),
+ ec.SECP521R1(),
)
with pytest.raises(ValueError):
numbers.public_key(backend)
@@ -478,71 +498,54 @@ class TestECDSAVectors(object):
itertools.chain(
load_vectors_from_file(
os.path.join(
- "asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt"),
- load_fips_ecdsa_signing_vectors
+ "asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt"
+ ),
+ load_fips_ecdsa_signing_vectors,
),
load_vectors_from_file(
- os.path.join(
- "asymmetric", "ECDSA", "SECP256K1", "SigGen.txt"),
- load_fips_ecdsa_signing_vectors
+ os.path.join("asymmetric", "ECDSA", "SECP256K1", "SigGen.txt"),
+ load_fips_ecdsa_signing_vectors,
),
- )
+ ),
)
def test_signatures(self, backend, vector):
- hash_type = _HASH_TYPES[vector['digest_algorithm']]
- curve_type = ec._CURVE_TYPES[vector['curve']]
+ hash_type = _HASH_TYPES[vector["digest_algorithm"]]
+ curve_type = ec._CURVE_TYPES[vector["curve"]]
_skip_ecdsa_vector(backend, curve_type, hash_type)
key = ec.EllipticCurvePublicNumbers(
- vector['x'],
- vector['y'],
- curve_type()
+ vector["x"], vector["y"], curve_type()
).public_key(backend)
- signature = encode_dss_signature(vector['r'], vector['s'])
+ signature = encode_dss_signature(vector["r"], vector["s"])
- key.verify(
- signature,
- vector['message'],
- ec.ECDSA(hash_type())
- )
+ key.verify(signature, vector["message"], ec.ECDSA(hash_type()))
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
- os.path.join(
- "asymmetric", "ECDSA", "FIPS_186-3", "SigVer.rsp"),
- load_fips_ecdsa_signing_vectors
- )
+ os.path.join("asymmetric", "ECDSA", "FIPS_186-3", "SigVer.rsp"),
+ load_fips_ecdsa_signing_vectors,
+ ),
)
def test_signature_failures(self, backend, vector):
- hash_type = _HASH_TYPES[vector['digest_algorithm']]
- curve_type = ec._CURVE_TYPES[vector['curve']]
+ hash_type = _HASH_TYPES[vector["digest_algorithm"]]
+ curve_type = ec._CURVE_TYPES[vector["curve"]]
_skip_ecdsa_vector(backend, curve_type, hash_type)
key = ec.EllipticCurvePublicNumbers(
- vector['x'],
- vector['y'],
- curve_type()
+ vector["x"], vector["y"], curve_type()
).public_key(backend)
- signature = encode_dss_signature(vector['r'], vector['s'])
+ signature = encode_dss_signature(vector["r"], vector["s"])
if vector["fail"] is True:
with pytest.raises(exceptions.InvalidSignature):
- key.verify(
- signature,
- vector['message'],
- ec.ECDSA(hash_type())
- )
+ key.verify(signature, vector["message"], ec.ECDSA(hash_type()))
else:
- key.verify(
- signature,
- vector['message'],
- ec.ECDSA(hash_type())
- )
+ key.verify(signature, vector["message"], ec.ECDSA(hash_type()))
def test_sign(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
@@ -595,9 +598,7 @@ class TestECDSAVectors(object):
h.update(message)
data = h.finalize()
public_key = private_key.public_key()
- public_key.verify(
- signature, data, ec.ECDSA(Prehashed(hashes.SHA1()))
- )
+ public_key.verify(signature, data, ec.ECDSA(Prehashed(hashes.SHA1())))
def test_verify_prehashed_digest_mismatch(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
@@ -615,20 +616,19 @@ class TestECDSAVectors(object):
def test_prehashed_unsupported_in_signer_ctx(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
private_key = ec.generate_private_key(ec.SECP256R1(), backend)
- with pytest.raises(TypeError), \
- pytest.warns(CryptographyDeprecationWarning):
+ with pytest.raises(TypeError), pytest.warns(
+ CryptographyDeprecationWarning
+ ):
private_key.signer(ec.ECDSA(Prehashed(hashes.SHA1())))
def test_prehashed_unsupported_in_verifier_ctx(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
private_key = ec.generate_private_key(ec.SECP256R1(), backend)
public_key = private_key.public_key()
- with pytest.raises(TypeError), \
- pytest.warns(CryptographyDeprecationWarning):
- public_key.verifier(
- b"0" * 64,
- ec.ECDSA(Prehashed(hashes.SHA1()))
- )
+ with pytest.raises(TypeError), pytest.warns(
+ CryptographyDeprecationWarning
+ ):
+ public_key.verifier(b"0" * 64, ec.ECDSA(Prehashed(hashes.SHA1())))
class TestECNumbersEquality(object):
@@ -676,28 +676,28 @@ class TestECSerialization(object):
itertools.product(
[
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.PrivateFormat.PKCS8
+ serialization.PrivateFormat.PKCS8,
],
[
b"s",
b"longerpassword",
b"!*$&(@#$*&($T@%_somesymbols",
b"\x01" * 1000,
- ]
- )
+ ],
+ ),
)
def test_private_bytes_encrypted_pem(self, backend, fmt, password):
+ skip_fips_traditional_openssl(backend, fmt)
_skip_curve_unsupported(backend, ec.SECP256R1())
key_bytes = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
- lambda pemfile: pemfile.read().encode()
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
+ lambda pemfile: pemfile.read().encode(),
)
key = serialization.load_pem_private_key(key_bytes, None, backend)
serialized = key.private_bytes(
serialization.Encoding.PEM,
fmt,
- serialization.BestAvailableEncryption(password)
+ serialization.BestAvailableEncryption(password),
)
loaded_key = serialization.load_pem_private_key(
serialized, password, backend
@@ -713,7 +713,7 @@ class TestECSerialization(object):
(serialization.Encoding.DER, serialization.PrivateFormat.Raw),
(serialization.Encoding.Raw, serialization.PrivateFormat.Raw),
(serialization.Encoding.X962, serialization.PrivateFormat.PKCS8),
- ]
+ ],
)
def test_private_bytes_rejects_invalid(self, encoding, fmt, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
@@ -727,21 +727,20 @@ class TestECSerialization(object):
[serialization.PrivateFormat.PKCS8, b"s"],
[serialization.PrivateFormat.PKCS8, b"longerpassword"],
[serialization.PrivateFormat.PKCS8, b"!*$&(@#$*&($T@%_somesymbol"],
- [serialization.PrivateFormat.PKCS8, b"\x01" * 1000]
- ]
+ [serialization.PrivateFormat.PKCS8, b"\x01" * 1000],
+ ],
)
def test_private_bytes_encrypted_der(self, backend, fmt, password):
_skip_curve_unsupported(backend, ec.SECP256R1())
key_bytes = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
- lambda pemfile: pemfile.read().encode()
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
+ lambda pemfile: pemfile.read().encode(),
)
key = serialization.load_pem_private_key(key_bytes, None, backend)
serialized = key.private_bytes(
serialization.Encoding.DER,
fmt,
- serialization.BestAvailableEncryption(password)
+ serialization.BestAvailableEncryption(password),
)
loaded_key = serialization.load_der_private_key(
serialized, password, backend
@@ -756,32 +755,32 @@ class TestECSerialization(object):
[
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
],
[
serialization.Encoding.DER,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
],
[
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
],
[
serialization.Encoding.DER,
serialization.PrivateFormat.PKCS8,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
],
- ]
+ ],
)
- def test_private_bytes_unencrypted(self, backend, encoding, fmt,
- loader_func):
+ def test_private_bytes_unencrypted(
+ self, backend, encoding, fmt, loader_func
+ ):
_skip_curve_unsupported(backend, ec.SECP256R1())
key_bytes = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
- lambda pemfile: pemfile.read().encode()
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
+ lambda pemfile: pemfile.read().encode(),
)
key = serialization.load_pem_private_key(key_bytes, None, backend)
serialized = key.private_bytes(
@@ -792,6 +791,9 @@ class TestECSerialization(object):
priv_num = key.private_numbers()
assert loaded_priv_num == priv_num
+ @pytest.mark.skip_fips(
+ reason="Traditional OpenSSL key format is not supported in FIPS mode."
+ )
@pytest.mark.parametrize(
("key_path", "encoding", "loader_func"),
[
@@ -800,16 +802,16 @@ class TestECSerialization(object):
"asymmetric", "PEM_Serialization", "ec_private_key.pem"
),
serialization.Encoding.PEM,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
],
[
os.path.join(
"asymmetric", "DER_Serialization", "ec_private_key.der"
),
serialization.Encoding.DER,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
],
- ]
+ ],
)
def test_private_bytes_traditional_openssl_unencrypted(
self, backend, key_path, encoding, loader_func
@@ -822,103 +824,97 @@ class TestECSerialization(object):
serialized = key.private_bytes(
encoding,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
assert serialized == key_bytes
def test_private_bytes_traditional_der_encrypted_invalid(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.DER,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.BestAvailableEncryption(b"password")
+ serialization.BestAvailableEncryption(b"password"),
)
def test_private_bytes_invalid_encoding(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with pytest.raises(TypeError):
key.private_bytes(
"notencoding",
serialization.PrivateFormat.PKCS8,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_private_bytes_invalid_format(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with pytest.raises(TypeError):
key.private_bytes(
serialization.Encoding.PEM,
"invalidformat",
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_private_bytes_invalid_encryption_algorithm(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with pytest.raises(TypeError):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- "notanencalg"
+ "notanencalg",
)
def test_private_bytes_unsupported_encryption_type(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- DummyKeySerializationEncryption()
+ DummyKeySerializationEncryption(),
)
def test_public_bytes_from_derived_public_key(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
public = key.public_key()
pem = public.public_bytes(
serialization.Encoding.PEM,
- serialization.PublicFormat.SubjectPublicKeyInfo
+ serialization.PublicFormat.SubjectPublicKeyInfo,
)
parsed_public = serialization.load_pem_public_key(pem, backend)
assert parsed_public
@@ -936,24 +932,27 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
),
serialization.load_pem_public_key,
serialization.Encoding.PEM,
- ), (
+ ),
+ (
os.path.join(
"asymmetric", "DER_Serialization", "ec_public_key.der"
),
serialization.load_der_public_key,
serialization.Encoding.DER,
- )
- ]
+ ),
+ ],
)
- def test_public_bytes_match(self, key_path, loader_func, encoding,
- backend):
+ def test_public_bytes_match(
+ self, key_path, loader_func, encoding, backend
+ ):
_skip_curve_unsupported(backend, ec.SECP256R1())
key_bytes = load_vectors_from_file(
key_path, lambda pemfile: pemfile.read(), mode="rb"
)
key = loader_func(key_bytes, backend)
serialized = key.public_bytes(
- encoding, serialization.PublicFormat.SubjectPublicKeyInfo,
+ encoding,
+ serialization.PublicFormat.SubjectPublicKeyInfo,
)
assert serialized == key_bytes
@@ -965,7 +964,8 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
os.path.join(
"asymmetric", "PEM_Serialization", "ec_public_key.pem"
),
- lambda pemfile: pemfile.read(), mode="rb"
+ lambda pemfile: pemfile.read(),
+ mode="rb",
)
key = serialization.load_pem_public_key(key_bytes, backend)
@@ -982,7 +982,7 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
with pytest.raises(ValueError):
key.public_bytes(
serialization.Encoding.OpenSSH,
- serialization.PublicFormat.OpenSSH
+ serialization.PublicFormat.OpenSSH,
)
def test_public_bytes_invalid_encoding(self, backend):
@@ -993,35 +993,37 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
),
lambda pemfile: serialization.load_pem_public_key(
pemfile.read().encode(), backend
- )
+ ),
)
with pytest.raises(TypeError):
key.public_bytes(
- "notencoding",
- serialization.PublicFormat.SubjectPublicKeyInfo
+ "notencoding", serialization.PublicFormat.SubjectPublicKeyInfo
)
@pytest.mark.parametrize(
("encoding", "fmt"),
- list(itertools.product(
- [
- serialization.Encoding.Raw,
- serialization.Encoding.X962,
- serialization.Encoding.PEM,
- serialization.Encoding.DER
- ],
- [
- serialization.PublicFormat.Raw,
- ]
- )) + list(itertools.product(
- [serialization.Encoding.Raw],
- [
- serialization.PublicFormat.SubjectPublicKeyInfo,
- serialization.PublicFormat.PKCS1,
- serialization.PublicFormat.UncompressedPoint,
- serialization.PublicFormat.CompressedPoint,
- ]
- ))
+ list(
+ itertools.product(
+ [
+ serialization.Encoding.Raw,
+ serialization.Encoding.X962,
+ serialization.Encoding.PEM,
+ serialization.Encoding.DER,
+ ],
+ [serialization.PublicFormat.Raw],
+ )
+ )
+ + list(
+ itertools.product(
+ [serialization.Encoding.Raw],
+ [
+ serialization.PublicFormat.SubjectPublicKeyInfo,
+ serialization.PublicFormat.PKCS1,
+ serialization.PublicFormat.UncompressedPoint,
+ serialization.PublicFormat.CompressedPoint,
+ ],
+ )
+ ),
)
def test_public_bytes_rejects_invalid(self, encoding, fmt, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
@@ -1037,7 +1039,7 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
),
lambda pemfile: serialization.load_pem_public_key(
pemfile.read().encode(), backend
- )
+ ),
)
with pytest.raises(TypeError):
key.public_bytes(serialization.Encoding.PEM, "invalidformat")
@@ -1050,7 +1052,7 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
),
lambda pemfile: serialization.load_pem_public_key(
pemfile.read().encode(), backend
- )
+ ),
)
with pytest.raises(ValueError):
key.public_bytes(
@@ -1061,14 +1063,14 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
"vector",
load_vectors_from_file(
os.path.join("asymmetric", "EC", "compressed_points.txt"),
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
- def test_from_encoded_point_compressed(self, vector):
- curve = {
- b"SECP256R1": ec.SECP256R1(),
- b"SECP256K1": ec.SECP256K1(),
- }[vector["curve"]]
+ def test_from_encoded_point_compressed(self, vector, backend):
+ curve = {b"SECP256R1": ec.SECP256R1(), b"SECP256K1": ec.SECP256K1()}[
+ vector["curve"]
+ ]
+ _skip_curve_unsupported(backend, curve)
point = binascii.unhexlify(vector["point"])
pn = ec.EllipticCurvePublicKey.from_encoded_point(curve, point)
public_num = pn.public_numbers()
@@ -1096,12 +1098,12 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
ec.SECP256R1(), uncompressed_point
)
assert pn.public_numbers().x == int(
- '7399336a9edf2197c2f8eb3d39aed9c34a66e45d918a07dc7684c42c9b37ac68',
- 16
+ "7399336a9edf2197c2f8eb3d39aed9c34a66e45d918a07dc7684c42c9b37ac68",
+ 16,
)
assert pn.public_numbers().y == int(
- '6699ececc4f5f0d756d3c450708a0694eb0a07a68b805070b40b058d27271f6d',
- 16
+ "6699ececc4f5f0d756d3c450708a0694eb0a07a68b805070b40b058d27271f6d",
+ 16,
)
def test_from_encoded_point_invalid_length(self):
@@ -1117,9 +1119,7 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
def test_from_encoded_point_empty_byte_string(self):
with pytest.raises(ValueError):
- ec.EllipticCurvePublicKey.from_encoded_point(
- ec.SECP384R1(), b""
- )
+ ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP384R1(), b"")
def test_from_encoded_point_not_a_curve(self):
with pytest.raises(TypeError):
@@ -1141,31 +1141,37 @@ class TestEllipticCurvePEMPublicKeySerialization(object):
"vector",
load_vectors_from_file(
os.path.join("asymmetric", "EC", "compressed_points.txt"),
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_serialize_point(self, vector, backend):
- curve = {
- b"SECP256R1": ec.SECP256R1(),
- b"SECP256K1": ec.SECP256K1(),
- }[vector["curve"]]
+ curve = {b"SECP256R1": ec.SECP256R1(), b"SECP256K1": ec.SECP256K1()}[
+ vector["curve"]
+ ]
+ _skip_curve_unsupported(backend, curve)
point = binascii.unhexlify(vector["point"])
key = ec.EllipticCurvePublicKey.from_encoded_point(curve, point)
key2 = ec.EllipticCurvePublicKey.from_encoded_point(
curve,
key.public_bytes(
serialization.Encoding.X962,
- serialization.PublicFormat.UncompressedPoint
+ serialization.PublicFormat.UncompressedPoint,
+ ),
+ )
+ assert (
+ key.public_bytes(
+ serialization.Encoding.X962,
+ serialization.PublicFormat.CompressedPoint,
+ )
+ == point
+ )
+ assert (
+ key2.public_bytes(
+ serialization.Encoding.X962,
+ serialization.PublicFormat.CompressedPoint,
)
+ == point
)
- assert key.public_bytes(
- serialization.Encoding.X962,
- serialization.PublicFormat.CompressedPoint
- ) == point
- assert key2.public_bytes(
- serialization.Encoding.X962,
- serialization.PublicFormat.CompressedPoint
- ) == point
@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
@@ -1174,8 +1180,9 @@ class TestECDSAVerification(object):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = ec.generate_private_key(ec.SECP256R1(), backend)
public_key = key.public_key()
- with pytest.raises(TypeError), \
- pytest.warns(CryptographyDeprecationWarning):
+ with pytest.raises(TypeError), pytest.warns(
+ CryptographyDeprecationWarning
+ ):
public_key.verifier(1234, ec.ECDSA(hashes.SHA256()))
@@ -1185,43 +1192,45 @@ class TestECDH(object):
"vector",
load_vectors_from_file(
os.path.join(
- "asymmetric", "ECDH",
- "KASValidityTest_ECCStaticUnified_NOKC_ZZOnly_init.fax"),
- load_kasvs_ecdh_vectors
- )
+ "asymmetric",
+ "ECDH",
+ "KASValidityTest_ECCStaticUnified_NOKC_ZZOnly_init.fax",
+ ),
+ load_kasvs_ecdh_vectors,
+ ),
)
def test_key_exchange_with_vectors(self, backend, vector):
_skip_exchange_algorithm_unsupported(
- backend, ec.ECDH(), ec._CURVE_TYPES[vector['curve']]
+ backend, ec.ECDH(), ec._CURVE_TYPES[vector["curve"]]
)
- key_numbers = vector['IUT']
+ key_numbers = vector["IUT"]
private_numbers = ec.EllipticCurvePrivateNumbers(
- key_numbers['d'],
+ key_numbers["d"],
ec.EllipticCurvePublicNumbers(
- key_numbers['x'],
- key_numbers['y'],
- ec._CURVE_TYPES[vector['curve']]()
- )
+ key_numbers["x"],
+ key_numbers["y"],
+ ec._CURVE_TYPES[vector["curve"]](),
+ ),
)
# Errno 5-7 indicates a bad public or private key, this doesn't test
# the ECDH code at all
- if vector['fail'] and vector['errno'] in [5, 6, 7]:
+ if vector["fail"] and vector["errno"] in [5, 6, 7]:
with pytest.raises(ValueError):
private_numbers.private_key(backend)
return
else:
private_key = private_numbers.private_key(backend)
- peer_numbers = vector['CAVS']
+ peer_numbers = vector["CAVS"]
public_numbers = ec.EllipticCurvePublicNumbers(
- peer_numbers['x'],
- peer_numbers['y'],
- ec._CURVE_TYPES[vector['curve']]()
+ peer_numbers["x"],
+ peer_numbers["y"],
+ ec._CURVE_TYPES[vector["curve"]](),
)
# Errno 1 and 2 indicates a bad public key, this doesn't test the ECDH
# code at all
- if vector['fail'] and vector['errno'] in [1, 2]:
+ if vector["fail"] and vector["errno"] in [1, 2]:
with pytest.raises(ValueError):
public_numbers.public_key(backend)
return
@@ -1229,37 +1238,37 @@ class TestECDH(object):
peer_pubkey = public_numbers.public_key(backend)
z = private_key.exchange(ec.ECDH(), peer_pubkey)
- z = int(hexlify(z).decode('ascii'), 16)
+ z = int(hexlify(z).decode("ascii"), 16)
# At this point fail indicates that one of the underlying keys was
# changed. This results in a non-matching derived key.
- if vector['fail']:
+ if vector["fail"]:
# Errno 8 indicates Z should be changed.
- assert vector['errno'] == 8
- assert z != vector['Z']
+ assert vector["errno"] == 8
+ assert z != vector["Z"]
else:
- assert z == vector['Z']
+ assert z == vector["Z"]
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
os.path.join("asymmetric", "ECDH", "brainpool.txt"),
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_brainpool_kex(self, backend, vector):
- curve = ec._CURVE_TYPES[vector['curve'].decode('ascii')]
+ curve = ec._CURVE_TYPES[vector["curve"].decode("ascii")]
_skip_exchange_algorithm_unsupported(backend, ec.ECDH(), curve)
key = ec.EllipticCurvePrivateNumbers(
- int(vector['da'], 16),
+ int(vector["da"], 16),
ec.EllipticCurvePublicNumbers(
- int(vector['x_qa'], 16), int(vector['y_qa'], 16), curve()
- )
+ int(vector["x_qa"], 16), int(vector["y_qa"], 16), curve()
+ ),
).private_key(backend)
peer = ec.EllipticCurvePrivateNumbers(
- int(vector['db'], 16),
+ int(vector["db"], 16),
ec.EllipticCurvePublicNumbers(
- int(vector['x_qb'], 16), int(vector['y_qb'], 16), curve()
- )
+ int(vector["x_qb"], 16), int(vector["y_qb"], 16), curve()
+ ),
).private_key(backend)
shared_secret = key.exchange(ec.ECDH(), peer.public_key())
assert shared_secret == binascii.unhexlify(vector["x_z"])
@@ -1270,11 +1279,10 @@ class TestECDH(object):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
with raises_unsupported_algorithm(
@@ -1287,11 +1295,10 @@ class TestECDH(object):
_skip_curve_unsupported(backend, ec.SECP384R1())
key = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "ec_private_key.pem"),
+ os.path.join("asymmetric", "PKCS8", "ec_private_key.pem"),
lambda pemfile: serialization.load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
public_key = EC_KEY_SECP384R1.public_numbers.public_key(backend)
diff --git a/tests/hazmat/primitives/test_ed25519.py b/tests/hazmat/primitives/test_ed25519.py
new file mode 100644
index 000000000..5b003d1e4
--- /dev/null
+++ b/tests/hazmat/primitives/test_ed25519.py
@@ -0,0 +1,232 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import os
+
+import pytest
+
+from cryptography.exceptions import InvalidSignature, _Reasons
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.ed25519 import (
+ Ed25519PrivateKey,
+ Ed25519PublicKey,
+)
+
+from ...utils import load_vectors_from_file, raises_unsupported_algorithm
+
+
+def load_ed25519_vectors(vector_data):
+ """
+ djb's ed25519 vectors are structured as a colon delimited array:
+ 0: secret key (32 bytes) + public key (32 bytes)
+ 1: public key (32 bytes)
+ 2: message (0+ bytes)
+ 3: signature + message (64+ bytes)
+ """
+ data = []
+ for line in vector_data:
+ secret_key, public_key, message, signature, _ = line.split(":")
+ secret_key = secret_key[0:64]
+ signature = signature[0:128]
+ data.append(
+ {
+ "secret_key": secret_key,
+ "public_key": public_key,
+ "message": message,
+ "signature": signature,
+ }
+ )
+ return data
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: not backend.ed25519_supported(),
+ skip_message="Requires OpenSSL without Ed25519 support",
+)
+def test_ed25519_unsupported(backend):
+ with raises_unsupported_algorithm(
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+ ):
+ Ed25519PublicKey.from_public_bytes(b"0" * 32)
+
+ with raises_unsupported_algorithm(
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+ ):
+ Ed25519PrivateKey.from_private_bytes(b"0" * 32)
+
+ with raises_unsupported_algorithm(
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+ ):
+ Ed25519PrivateKey.generate()
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+)
+class TestEd25519Signing(object):
+ @pytest.mark.parametrize(
+ "vector",
+ load_vectors_from_file(
+ os.path.join("asymmetric", "Ed25519", "sign.input"),
+ load_ed25519_vectors,
+ ),
+ )
+ def test_sign_verify_input(self, vector, backend):
+ sk = binascii.unhexlify(vector["secret_key"])
+ pk = binascii.unhexlify(vector["public_key"])
+ message = binascii.unhexlify(vector["message"])
+ signature = binascii.unhexlify(vector["signature"])
+ private_key = Ed25519PrivateKey.from_private_bytes(sk)
+ computed_sig = private_key.sign(message)
+ assert computed_sig == signature
+ public_key = private_key.public_key()
+ assert (
+ public_key.public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+ == pk
+ )
+ public_key.verify(signature, message)
+
+ def test_invalid_signature(self, backend):
+ key = Ed25519PrivateKey.generate()
+ signature = key.sign(b"test data")
+ with pytest.raises(InvalidSignature):
+ key.public_key().verify(signature, b"wrong data")
+
+ with pytest.raises(InvalidSignature):
+ key.public_key().verify(b"0" * 64, b"test data")
+
+ def test_generate(self, backend):
+ key = Ed25519PrivateKey.generate()
+ assert key
+ assert key.public_key()
+
+ def test_load_public_bytes(self, backend):
+ public_key = Ed25519PrivateKey.generate().public_key()
+ public_bytes = public_key.public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+ public_key2 = Ed25519PublicKey.from_public_bytes(public_bytes)
+ assert public_bytes == public_key2.public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+
+ def test_invalid_type_public_bytes(self, backend):
+ with pytest.raises(TypeError):
+ Ed25519PublicKey.from_public_bytes(object())
+
+ def test_invalid_type_private_bytes(self, backend):
+ with pytest.raises(TypeError):
+ Ed25519PrivateKey.from_private_bytes(object())
+
+ def test_invalid_length_from_public_bytes(self, backend):
+ with pytest.raises(ValueError):
+ Ed25519PublicKey.from_public_bytes(b"a" * 31)
+ with pytest.raises(ValueError):
+ Ed25519PublicKey.from_public_bytes(b"a" * 33)
+
+ def test_invalid_length_from_private_bytes(self, backend):
+ with pytest.raises(ValueError):
+ Ed25519PrivateKey.from_private_bytes(b"a" * 31)
+ with pytest.raises(ValueError):
+ Ed25519PrivateKey.from_private_bytes(b"a" * 33)
+
+ def test_invalid_private_bytes(self, backend):
+ key = Ed25519PrivateKey.generate()
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.Raw,
+ None,
+ )
+
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.PKCS8,
+ None,
+ )
+
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ serialization.Encoding.PEM,
+ serialization.PrivateFormat.Raw,
+ serialization.NoEncryption(),
+ )
+
+ def test_invalid_public_bytes(self, backend):
+ key = Ed25519PrivateKey.generate().public_key()
+ with pytest.raises(ValueError):
+ key.public_bytes(
+ serialization.Encoding.Raw,
+ serialization.PublicFormat.SubjectPublicKeyInfo,
+ )
+
+ with pytest.raises(ValueError):
+ key.public_bytes(
+ serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
+ )
+
+ with pytest.raises(ValueError):
+ key.public_bytes(
+ serialization.Encoding.PEM, serialization.PublicFormat.Raw
+ )
+
+ @pytest.mark.parametrize(
+ ("encoding", "fmt", "encryption", "passwd", "load_func"),
+ [
+ (
+ serialization.Encoding.PEM,
+ serialization.PrivateFormat.PKCS8,
+ serialization.BestAvailableEncryption(b"password"),
+ b"password",
+ serialization.load_pem_private_key,
+ ),
+ (
+ serialization.Encoding.DER,
+ serialization.PrivateFormat.PKCS8,
+ serialization.BestAvailableEncryption(b"password"),
+ b"password",
+ serialization.load_der_private_key,
+ ),
+ (
+ serialization.Encoding.PEM,
+ serialization.PrivateFormat.PKCS8,
+ serialization.NoEncryption(),
+ None,
+ serialization.load_pem_private_key,
+ ),
+ (
+ serialization.Encoding.DER,
+ serialization.PrivateFormat.PKCS8,
+ serialization.NoEncryption(),
+ None,
+ serialization.load_der_private_key,
+ ),
+ ],
+ )
+ def test_round_trip_private_serialization(
+ self, encoding, fmt, encryption, passwd, load_func, backend
+ ):
+ key = Ed25519PrivateKey.generate()
+ serialized = key.private_bytes(encoding, fmt, encryption)
+ loaded_key = load_func(serialized, passwd, backend)
+ assert isinstance(loaded_key, Ed25519PrivateKey)
+
+ def test_buffer_protocol(self, backend):
+ private_bytes = os.urandom(32)
+ key = Ed25519PrivateKey.from_private_bytes(bytearray(private_bytes))
+ assert (
+ key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.Raw,
+ serialization.NoEncryption(),
+ )
+ == private_bytes
+ )
diff --git a/tests/hazmat/primitives/test_ed448.py b/tests/hazmat/primitives/test_ed448.py
new file mode 100644
index 000000000..9a1f90569
--- /dev/null
+++ b/tests/hazmat/primitives/test_ed448.py
@@ -0,0 +1,256 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import os
+
+import pytest
+
+from cryptography.exceptions import InvalidSignature, _Reasons
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric.ed448 import (
+ Ed448PrivateKey,
+ Ed448PublicKey,
+)
+
+from ...utils import (
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
+)
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: not backend.ed448_supported(),
+ skip_message="Requires OpenSSL without Ed448 support",
+)
+def test_ed448_unsupported(backend):
+ with raises_unsupported_algorithm(
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+ ):
+ Ed448PublicKey.from_public_bytes(b"0" * 57)
+
+ with raises_unsupported_algorithm(
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+ ):
+ Ed448PrivateKey.from_private_bytes(b"0" * 57)
+
+ with raises_unsupported_algorithm(
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+ ):
+ Ed448PrivateKey.generate()
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+)
+class TestEd448Signing(object):
+ @pytest.mark.parametrize(
+ "vector",
+ load_vectors_from_file(
+ os.path.join("asymmetric", "Ed448", "rfc8032.txt"),
+ load_nist_vectors,
+ ),
+ )
+ def test_sign_input(self, vector, backend):
+ if vector.get("context") is not None:
+ pytest.skip("ed448 contexts are not currently supported")
+
+ sk = binascii.unhexlify(vector["secret"])
+ pk = binascii.unhexlify(vector["public"])
+ message = binascii.unhexlify(vector["message"])
+ signature = binascii.unhexlify(vector["signature"])
+ private_key = Ed448PrivateKey.from_private_bytes(sk)
+ computed_sig = private_key.sign(message)
+ assert computed_sig == signature
+ public_key = private_key.public_key()
+ assert (
+ public_key.public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+ == pk
+ )
+ public_key.verify(signature, message)
+
+ def test_invalid_signature(self, backend):
+ key = Ed448PrivateKey.generate()
+ signature = key.sign(b"test data")
+ with pytest.raises(InvalidSignature):
+ key.public_key().verify(signature, b"wrong data")
+
+ with pytest.raises(InvalidSignature):
+ key.public_key().verify(b"0" * 64, b"test data")
+
+ def test_generate(self, backend):
+ key = Ed448PrivateKey.generate()
+ assert key
+ assert key.public_key()
+
+ @pytest.mark.parametrize(
+ "vector",
+ load_vectors_from_file(
+ os.path.join("asymmetric", "Ed448", "rfc8032.txt"),
+ load_nist_vectors,
+ ),
+ )
+ def test_pub_priv_bytes_raw(self, vector, backend):
+ sk = binascii.unhexlify(vector["secret"])
+ pk = binascii.unhexlify(vector["public"])
+ private_key = Ed448PrivateKey.from_private_bytes(sk)
+ assert (
+ private_key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.Raw,
+ serialization.NoEncryption(),
+ )
+ == sk
+ )
+ assert (
+ private_key.public_key().public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+ == pk
+ )
+ public_key = Ed448PublicKey.from_public_bytes(pk)
+ assert (
+ public_key.public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+ == pk
+ )
+
+ @pytest.mark.parametrize(
+ ("encoding", "fmt", "encryption", "passwd", "load_func"),
+ [
+ (
+ serialization.Encoding.PEM,
+ serialization.PrivateFormat.PKCS8,
+ serialization.BestAvailableEncryption(b"password"),
+ b"password",
+ serialization.load_pem_private_key,
+ ),
+ (
+ serialization.Encoding.DER,
+ serialization.PrivateFormat.PKCS8,
+ serialization.BestAvailableEncryption(b"password"),
+ b"password",
+ serialization.load_der_private_key,
+ ),
+ (
+ serialization.Encoding.PEM,
+ serialization.PrivateFormat.PKCS8,
+ serialization.NoEncryption(),
+ None,
+ serialization.load_pem_private_key,
+ ),
+ (
+ serialization.Encoding.DER,
+ serialization.PrivateFormat.PKCS8,
+ serialization.NoEncryption(),
+ None,
+ serialization.load_der_private_key,
+ ),
+ ],
+ )
+ def test_round_trip_private_serialization(
+ self, encoding, fmt, encryption, passwd, load_func, backend
+ ):
+ key = Ed448PrivateKey.generate()
+ serialized = key.private_bytes(encoding, fmt, encryption)
+ loaded_key = load_func(serialized, passwd, backend)
+ assert isinstance(loaded_key, Ed448PrivateKey)
+
+ def test_invalid_type_public_bytes(self, backend):
+ with pytest.raises(TypeError):
+ Ed448PublicKey.from_public_bytes(object())
+
+ def test_invalid_type_private_bytes(self, backend):
+ with pytest.raises(TypeError):
+ Ed448PrivateKey.from_private_bytes(object())
+
+ def test_invalid_length_from_public_bytes(self, backend):
+ with pytest.raises(ValueError):
+ Ed448PublicKey.from_public_bytes(b"a" * 56)
+ with pytest.raises(ValueError):
+ Ed448PublicKey.from_public_bytes(b"a" * 58)
+
+ def test_invalid_length_from_private_bytes(self, backend):
+ with pytest.raises(ValueError):
+ Ed448PrivateKey.from_private_bytes(b"a" * 56)
+ with pytest.raises(ValueError):
+ Ed448PrivateKey.from_private_bytes(b"a" * 58)
+
+ def test_invalid_private_bytes(self, backend):
+ key = Ed448PrivateKey.generate()
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.Raw,
+ None,
+ )
+
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.PKCS8,
+ None,
+ )
+
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ serialization.Encoding.PEM,
+ serialization.PrivateFormat.Raw,
+ serialization.NoEncryption(),
+ )
+
+ def test_invalid_public_bytes(self, backend):
+ key = Ed448PrivateKey.generate().public_key()
+ with pytest.raises(ValueError):
+ key.public_bytes(
+ serialization.Encoding.Raw,
+ serialization.PublicFormat.SubjectPublicKeyInfo,
+ )
+
+ with pytest.raises(ValueError):
+ key.public_bytes(
+ serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
+ )
+
+ with pytest.raises(ValueError):
+ key.public_bytes(
+ serialization.Encoding.PEM, serialization.PublicFormat.Raw
+ )
+
+ def test_buffer_protocol(self, backend):
+ private_bytes = os.urandom(57)
+ key = Ed448PrivateKey.from_private_bytes(bytearray(private_bytes))
+ assert (
+ key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.Raw,
+ serialization.NoEncryption(),
+ )
+ == private_bytes
+ )
+
+ def test_malleability(self, backend):
+ # This is a signature where r > the group order. It should be
+ # rejected to prevent signature malleability issues. This test can
+ # be removed when wycheproof grows ed448 vectors
+ public_bytes = binascii.unhexlify(
+ "fedb02a658d74990244d9d10cf338e977565cbbda6b24c716829ed6ee1e4f28cf"
+ "2620c052db8d878f6243bffc22242816c1aaa67d2f3603600"
+ )
+ signature = binascii.unhexlify(
+ "0cc16ba24d69277f927c1554b0f08a2a711bbdd20b058ccc660d00ca13542a3ce"
+ "f9e5c44c54ab23a2eb14f947e167b990b080863e28b399380f30db6e54d5d1406"
+ "d23378ffde11b1fb81b2b438a3b8e8aa7f7f4e1befcc905023fab5a5465053844"
+ "f04cf0c1b51d84760f869588687f57500"
+ )
+ key = Ed448PublicKey.from_public_bytes(public_bytes)
+ with pytest.raises(InvalidSignature):
+ key.verify(signature, b"8")
diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py
index 5225a00be..9301b6217 100644
--- a/tests/hazmat/primitives/test_hash_vectors.py
+++ b/tests/hazmat/primitives/test_hash_vectors.py
@@ -22,13 +22,10 @@ from ...utils import load_hash_vectors, load_nist_vectors
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA1(object):
- test_SHA1 = generate_hash_test(
+ test_sha1 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA1"),
- [
- "SHA1LongMsg.rsp",
- "SHA1ShortMsg.rsp",
- ],
+ ["SHA1LongMsg.rsp", "SHA1ShortMsg.rsp"],
hashes.SHA1(),
)
@@ -39,13 +36,10 @@ class TestSHA1(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA224(object):
- test_SHA224 = generate_hash_test(
+ test_sha224 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA2"),
- [
- "SHA224LongMsg.rsp",
- "SHA224ShortMsg.rsp",
- ],
+ ["SHA224LongMsg.rsp", "SHA224ShortMsg.rsp"],
hashes.SHA224(),
)
@@ -56,13 +50,10 @@ class TestSHA224(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA256(object):
- test_SHA256 = generate_hash_test(
+ test_sha256 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA2"),
- [
- "SHA256LongMsg.rsp",
- "SHA256ShortMsg.rsp",
- ],
+ ["SHA256LongMsg.rsp", "SHA256ShortMsg.rsp"],
hashes.SHA256(),
)
@@ -73,13 +64,10 @@ class TestSHA256(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA384(object):
- test_SHA384 = generate_hash_test(
+ test_sha384 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA2"),
- [
- "SHA384LongMsg.rsp",
- "SHA384ShortMsg.rsp",
- ],
+ ["SHA384LongMsg.rsp", "SHA384ShortMsg.rsp"],
hashes.SHA384(),
)
@@ -90,13 +78,10 @@ class TestSHA384(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA512(object):
- test_SHA512 = generate_hash_test(
+ test_sha512 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA2"),
- [
- "SHA512LongMsg.rsp",
- "SHA512ShortMsg.rsp",
- ],
+ ["SHA512LongMsg.rsp", "SHA512ShortMsg.rsp"],
hashes.SHA512(),
)
@@ -107,13 +92,10 @@ class TestSHA512(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA512224(object):
- test_SHA512_224 = generate_hash_test(
+ test_sha512_224 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA2"),
- [
- "SHA512_224LongMsg.rsp",
- "SHA512_224ShortMsg.rsp",
- ],
+ ["SHA512_224LongMsg.rsp", "SHA512_224ShortMsg.rsp"],
hashes.SHA512_224(),
)
@@ -124,13 +106,10 @@ class TestSHA512224(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA512256(object):
- test_SHA512_256 = generate_hash_test(
+ test_sha512_256 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA2"),
- [
- "SHA512_256LongMsg.rsp",
- "SHA512_256ShortMsg.rsp",
- ],
+ ["SHA512_256LongMsg.rsp", "SHA512_256ShortMsg.rsp"],
hashes.SHA512_256(),
)
@@ -144,16 +123,15 @@ class TestMD5(object):
test_md5 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "MD5"),
- [
- "rfc-1321.txt",
- ],
+ ["rfc-1321.txt"],
hashes.MD5(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.hash_supported(
- hashes.BLAKE2b(digest_size=64)),
+ hashes.BLAKE2b(digest_size=64)
+ ),
skip_message="Does not support BLAKE2b",
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
@@ -161,16 +139,15 @@ class TestBLAKE2b(object):
test_b2b = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "blake2"),
- [
- "blake2b.txt",
- ],
+ ["blake2b.txt"],
hashes.BLAKE2b(digest_size=64),
)
@pytest.mark.supported(
only_if=lambda backend: backend.hash_supported(
- hashes.BLAKE2s(digest_size=32)),
+ hashes.BLAKE2s(digest_size=32)
+ ),
skip_message="Does not support BLAKE2s",
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
@@ -178,9 +155,7 @@ class TestBLAKE2s256(object):
test_b2s = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "blake2"),
- [
- "blake2s.txt",
- ],
+ ["blake2s.txt"],
hashes.BLAKE2s(digest_size=32),
)
@@ -191,13 +166,10 @@ class TestBLAKE2s256(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA3224(object):
- test_SHA3_224 = generate_hash_test(
+ test_sha3_224 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA3"),
- [
- "SHA3_224LongMsg.rsp",
- "SHA3_224ShortMsg.rsp",
- ],
+ ["SHA3_224LongMsg.rsp", "SHA3_224ShortMsg.rsp"],
hashes.SHA3_224(),
)
@@ -208,13 +180,10 @@ class TestSHA3224(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA3256(object):
- test_SHA3_256 = generate_hash_test(
+ test_sha3_256 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA3"),
- [
- "SHA3_256LongMsg.rsp",
- "SHA3_256ShortMsg.rsp",
- ],
+ ["SHA3_256LongMsg.rsp", "SHA3_256ShortMsg.rsp"],
hashes.SHA3_256(),
)
@@ -225,13 +194,10 @@ class TestSHA3256(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA3384(object):
- test_SHA3_384 = generate_hash_test(
+ test_sha3_384 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA3"),
- [
- "SHA3_384LongMsg.rsp",
- "SHA3_384ShortMsg.rsp",
- ],
+ ["SHA3_384LongMsg.rsp", "SHA3_384ShortMsg.rsp"],
hashes.SHA3_384(),
)
@@ -242,20 +208,18 @@ class TestSHA3384(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA3512(object):
- test_SHA3_512 = generate_hash_test(
+ test_sha3_512 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHA3"),
- [
- "SHA3_512LongMsg.rsp",
- "SHA3_512ShortMsg.rsp",
- ],
+ ["SHA3_512LongMsg.rsp", "SHA3_512ShortMsg.rsp"],
hashes.SHA3_512(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.hash_supported(
- hashes.SHAKE128(digest_size=16)),
+ hashes.SHAKE128(digest_size=16)
+ ),
skip_message="Does not support SHAKE128",
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
@@ -263,10 +227,7 @@ class TestSHAKE128(object):
test_shake128 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHAKE"),
- [
- "SHAKE128LongMsg.rsp",
- "SHAKE128ShortMsg.rsp",
- ],
+ ["SHAKE128LongMsg.rsp", "SHAKE128ShortMsg.rsp"],
hashes.SHAKE128(digest_size=16),
)
@@ -274,24 +235,23 @@ class TestSHAKE128(object):
"vector",
_load_all_params(
os.path.join("hashes", "SHAKE"),
- [
- "SHAKE128VariableOut.rsp",
- ],
+ ["SHAKE128VariableOut.rsp"],
load_nist_vectors,
- )
+ ),
)
def test_shake128_variable(self, vector, backend):
- output_length = int(vector['outputlen']) // 8
- msg = binascii.unhexlify(vector['msg'])
+ output_length = int(vector["outputlen"]) // 8
+ msg = binascii.unhexlify(vector["msg"])
shake = hashes.SHAKE128(digest_size=output_length)
m = hashes.Hash(shake, backend=backend)
m.update(msg)
- assert m.finalize() == binascii.unhexlify(vector['output'])
+ assert m.finalize() == binascii.unhexlify(vector["output"])
@pytest.mark.supported(
only_if=lambda backend: backend.hash_supported(
- hashes.SHAKE256(digest_size=32)),
+ hashes.SHAKE256(digest_size=32)
+ ),
skip_message="Does not support SHAKE256",
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
@@ -299,10 +259,7 @@ class TestSHAKE256(object):
test_shake256 = generate_hash_test(
load_hash_vectors,
os.path.join("hashes", "SHAKE"),
- [
- "SHAKE256LongMsg.rsp",
- "SHAKE256ShortMsg.rsp",
- ],
+ ["SHAKE256LongMsg.rsp", "SHAKE256ShortMsg.rsp"],
hashes.SHAKE256(digest_size=32),
)
@@ -310,16 +267,14 @@ class TestSHAKE256(object):
"vector",
_load_all_params(
os.path.join("hashes", "SHAKE"),
- [
- "SHAKE256VariableOut.rsp",
- ],
+ ["SHAKE256VariableOut.rsp"],
load_nist_vectors,
- )
+ ),
)
def test_shake256_variable(self, vector, backend):
- output_length = int(vector['outputlen']) // 8
- msg = binascii.unhexlify(vector['msg'])
+ output_length = int(vector["outputlen"]) // 8
+ msg = binascii.unhexlify(vector["msg"])
shake = hashes.SHAKE256(digest_size=output_length)
m = hashes.Hash(shake, backend=backend)
m.update(msg)
- assert m.finalize() == binascii.unhexlify(vector['output'])
+ assert m.finalize() == binascii.unhexlify(vector["output"])
diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py
index b10fadcdc..eadd0febf 100644
--- a/tests/hazmat/primitives/test_hashes.py
+++ b/tests/hazmat/primitives/test_hashes.py
@@ -52,7 +52,7 @@ class TestHashContext(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA1(object):
- test_SHA1 = generate_base_hash_test(
+ test_sha1 = generate_base_hash_test(
hashes.SHA1(),
digest_size=20,
)
@@ -64,7 +64,7 @@ class TestSHA1(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA224(object):
- test_SHA224 = generate_base_hash_test(
+ test_sha224 = generate_base_hash_test(
hashes.SHA224(),
digest_size=28,
)
@@ -76,7 +76,7 @@ class TestSHA224(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA256(object):
- test_SHA256 = generate_base_hash_test(
+ test_sha256 = generate_base_hash_test(
hashes.SHA256(),
digest_size=32,
)
@@ -88,7 +88,7 @@ class TestSHA256(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA384(object):
- test_SHA384 = generate_base_hash_test(
+ test_sha384 = generate_base_hash_test(
hashes.SHA384(),
digest_size=48,
)
@@ -100,7 +100,7 @@ class TestSHA384(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestSHA512(object):
- test_SHA512 = generate_base_hash_test(
+ test_sha512 = generate_base_hash_test(
hashes.SHA512(),
digest_size=64,
)
@@ -112,7 +112,7 @@ class TestSHA512(object):
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestMD5(object):
- test_MD5 = generate_base_hash_test(
+ test_md5 = generate_base_hash_test(
hashes.MD5(),
digest_size=16,
)
@@ -120,12 +120,13 @@ class TestMD5(object):
@pytest.mark.supported(
only_if=lambda backend: backend.hash_supported(
- hashes.BLAKE2b(digest_size=64)),
+ hashes.BLAKE2b(digest_size=64)
+ ),
skip_message="Does not support BLAKE2b",
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestBLAKE2b(object):
- test_BLAKE2b = generate_base_hash_test(
+ test_blake2b = generate_base_hash_test(
hashes.BLAKE2b(digest_size=64),
digest_size=64,
)
@@ -143,12 +144,13 @@ class TestBLAKE2b(object):
@pytest.mark.supported(
only_if=lambda backend: backend.hash_supported(
- hashes.BLAKE2s(digest_size=32)),
+ hashes.BLAKE2s(digest_size=32)
+ ),
skip_message="Does not support BLAKE2s",
)
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestBLAKE2s(object):
- test_BLAKE2s = generate_base_hash_test(
+ test_blake2s = generate_base_hash_test(
hashes.BLAKE2s(digest_size=32),
digest_size=32,
)
@@ -182,18 +184,12 @@ def test_buffer_protocol_hash(backend):
class TestSHAKE(object):
- @pytest.mark.parametrize(
- "xof",
- [hashes.SHAKE128, hashes.SHAKE256]
- )
+ @pytest.mark.parametrize("xof", [hashes.SHAKE128, hashes.SHAKE256])
def test_invalid_digest_type(self, xof):
with pytest.raises(TypeError):
xof(digest_size=object())
- @pytest.mark.parametrize(
- "xof",
- [hashes.SHAKE128, hashes.SHAKE256]
- )
+ @pytest.mark.parametrize("xof", [hashes.SHAKE128, hashes.SHAKE256])
def test_invalid_digest_size(self, xof):
with pytest.raises(ValueError):
xof(digest_size=-5)
diff --git a/tests/hazmat/primitives/test_hkdf.py b/tests/hazmat/primitives/test_hkdf.py
index 195bfb3a4..1d7de6c47 100644
--- a/tests/hazmat/primitives/test_hkdf.py
+++ b/tests/hazmat/primitives/test_hkdf.py
@@ -9,15 +9,15 @@ import os
import pytest
-from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, _Reasons
-)
+from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand
from ...utils import (
- load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
@@ -32,127 +32,67 @@ class TestHKDF(object):
big_length,
salt=None,
info=None,
- backend=backend
+ backend=backend,
)
def test_already_finalized(self, backend):
- hkdf = HKDF(
- hashes.SHA256(),
- 16,
- salt=None,
- info=None,
- backend=backend
- )
+ hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
hkdf.derive(b"\x01" * 16)
with pytest.raises(AlreadyFinalized):
hkdf.derive(b"\x02" * 16)
- hkdf = HKDF(
- hashes.SHA256(),
- 16,
- salt=None,
- info=None,
- backend=backend
- )
+ hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
hkdf.verify(b"\x01" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
with pytest.raises(AlreadyFinalized):
hkdf.verify(b"\x02" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
- hkdf = HKDF(
- hashes.SHA256(),
- 16,
- salt=None,
- info=None,
- backend=backend
- )
+ hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
def test_verify(self, backend):
- hkdf = HKDF(
- hashes.SHA256(),
- 16,
- salt=None,
- info=None,
- backend=backend
- )
+ hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
hkdf.verify(b"\x01" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
def test_verify_invalid(self, backend):
- hkdf = HKDF(
- hashes.SHA256(),
- 16,
- salt=None,
- info=None,
- backend=backend
- )
+ hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
with pytest.raises(InvalidKey):
hkdf.verify(b"\x02" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
def test_unicode_typeerror(self, backend):
with pytest.raises(TypeError):
- HKDF(
- hashes.SHA256(),
- 16,
- salt=u"foo",
- info=None,
- backend=backend
- )
+ HKDF(hashes.SHA256(), 16, salt=u"foo", info=None, backend=backend)
with pytest.raises(TypeError):
- HKDF(
- hashes.SHA256(),
- 16,
- salt=None,
- info=u"foo",
- backend=backend
- )
+ HKDF(hashes.SHA256(), 16, salt=None, info=u"foo", backend=backend)
with pytest.raises(TypeError):
hkdf = HKDF(
- hashes.SHA256(),
- 16,
- salt=None,
- info=None,
- backend=backend
+ hashes.SHA256(), 16, salt=None, info=None, backend=backend
)
hkdf.derive(u"foo")
with pytest.raises(TypeError):
hkdf = HKDF(
- hashes.SHA256(),
- 16,
- salt=None,
- info=None,
- backend=backend
+ hashes.SHA256(), 16, salt=None, info=None, backend=backend
)
hkdf.verify(u"foo", b"bar")
with pytest.raises(TypeError):
hkdf = HKDF(
- hashes.SHA256(),
- 16,
- salt=None,
- info=None,
- backend=backend
+ hashes.SHA256(), 16, salt=None, info=None, backend=backend
)
hkdf.verify(b"foo", u"bar")
def test_derive_short_output(self, backend):
- hkdf = HKDF(
- hashes.SHA256(),
- 4,
- salt=None,
- info=None,
- backend=backend
- )
+ hkdf = HKDF(hashes.SHA256(), 4, salt=None, info=None, backend=backend)
assert hkdf.derive(b"\x01" * 16) == b"gJ\xfb{"
@@ -165,7 +105,7 @@ class TestHKDF(object):
int(vector["l"]),
salt=vector["salt"],
info=vector["info"],
- backend=backend
+ backend=backend,
)
ikm = binascii.unhexlify(vector["ikm"])
@@ -180,7 +120,7 @@ class TestHKDF(object):
int(vector["l"]),
salt=vector["salt"],
info=vector["info"],
- backend=backend
+ backend=backend,
)
ikm = bytearray(binascii.unhexlify(vector["ikm"]))
@@ -194,8 +134,10 @@ class TestHKDFExpand(object):
b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
)
- okm = (b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
- b"5bf34007208d5b887185865")
+ okm = (
+ b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
+ b"5bf34007208d5b887185865"
+ )
info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
@@ -203,12 +145,17 @@ class TestHKDFExpand(object):
assert binascii.hexlify(hkdf.derive(prk)) == okm
def test_buffer_protocol(self, backend):
- prk = bytearray(binascii.unhexlify(
- b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
- ))
+ prk = bytearray(
+ binascii.unhexlify(
+ b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2"
+ b"b3e5"
+ )
+ )
- okm = (b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
- b"5bf34007208d5b887185865")
+ okm = (
+ b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
+ b"5bf34007208d5b887185865"
+ )
info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
@@ -220,8 +167,10 @@ class TestHKDFExpand(object):
b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
)
- okm = (b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
- b"5bf34007208d5b887185865")
+ okm = (
+ b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
+ b"5bf34007208d5b887185865"
+ )
info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
diff --git a/tests/hazmat/primitives/test_hkdf_vectors.py b/tests/hazmat/primitives/test_hkdf_vectors.py
index 74bf9291b..97385e203 100644
--- a/tests/hazmat/primitives/test_hkdf_vectors.py
+++ b/tests/hazmat/primitives/test_hkdf_vectors.py
@@ -17,27 +17,27 @@ from ...utils import load_nist_vectors
@pytest.mark.supported(
only_if=lambda backend: backend.hmac_supported(hashes.SHA1()),
- skip_message="Does not support SHA1."
+ skip_message="Does not support SHA1.",
)
@pytest.mark.requires_backend_interface(interface=HMACBackend)
class TestHKDFSHA1(object):
- test_HKDFSHA1 = generate_hkdf_test(
+ test_hkdfsha1 = generate_hkdf_test(
load_nist_vectors,
os.path.join("KDF"),
["rfc-5869-HKDF-SHA1.txt"],
- hashes.SHA1()
+ hashes.SHA1(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.hmac_supported(hashes.SHA256()),
- skip_message="Does not support SHA256."
+ skip_message="Does not support SHA256.",
)
@pytest.mark.requires_backend_interface(interface=HMACBackend)
class TestHKDFSHA256(object):
- test_HKDFSHA1 = generate_hkdf_test(
+ test_hkdfsha256 = generate_hkdf_test(
load_nist_vectors,
os.path.join("KDF"),
["rfc-5869-HKDF-SHA256.txt"],
- hashes.SHA256()
+ hashes.SHA256(),
)
diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py
index 0e2fe688a..7ea931aca 100644
--- a/tests/hazmat/primitives/test_hmac.py
+++ b/tests/hazmat/primitives/test_hmac.py
@@ -9,7 +9,9 @@ import binascii
import pytest
from cryptography.exceptions import (
- AlreadyFinalized, InvalidSignature, _Reasons
+ AlreadyFinalized,
+ InvalidSignature,
+ _Reasons,
)
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import hashes, hmac
@@ -55,27 +57,27 @@ class TestHMAC(object):
h.finalize()
def test_verify(self, backend):
- h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+ h = hmac.HMAC(b"", hashes.SHA1(), backend=backend)
digest = h.finalize()
- h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+ h = hmac.HMAC(b"", hashes.SHA1(), backend=backend)
h.verify(digest)
with pytest.raises(AlreadyFinalized):
- h.verify(b'')
+ h.verify(b"")
def test_invalid_verify(self, backend):
- h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+ h = hmac.HMAC(b"", hashes.SHA1(), backend=backend)
with pytest.raises(InvalidSignature):
- h.verify(b'')
+ h.verify(b"")
with pytest.raises(AlreadyFinalized):
- h.verify(b'')
+ h.verify(b"")
def test_verify_reject_unicode(self, backend):
- h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+ h = hmac.HMAC(b"", hashes.SHA1(), backend=backend)
with pytest.raises(TypeError):
- h.verify(u'')
+ h.verify(u"")
def test_unsupported_hash(self, backend):
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH):
diff --git a/tests/hazmat/primitives/test_hmac_vectors.py b/tests/hazmat/primitives/test_hmac_vectors.py
index 6ff71fe38..b39df1a75 100644
--- a/tests/hazmat/primitives/test_hmac_vectors.py
+++ b/tests/hazmat/primitives/test_hmac_vectors.py
@@ -24,9 +24,7 @@ class TestHMACMD5(object):
test_hmac_md5 = generate_hmac_test(
load_hash_vectors,
"HMAC",
- [
- "rfc-2202-md5.txt",
- ],
+ ["rfc-2202-md5.txt"],
hashes.MD5(),
)
@@ -40,9 +38,7 @@ class TestHMACSHA1(object):
test_hmac_sha1 = generate_hmac_test(
load_hash_vectors,
"HMAC",
- [
- "rfc-2202-sha1.txt",
- ],
+ ["rfc-2202-sha1.txt"],
hashes.SHA1(),
)
@@ -56,9 +52,7 @@ class TestHMACSHA224(object):
test_hmac_sha224 = generate_hmac_test(
load_hash_vectors,
"HMAC",
- [
- "rfc-4231-sha224.txt",
- ],
+ ["rfc-4231-sha224.txt"],
hashes.SHA224(),
)
@@ -72,9 +66,7 @@ class TestHMACSHA256(object):
test_hmac_sha256 = generate_hmac_test(
load_hash_vectors,
"HMAC",
- [
- "rfc-4231-sha256.txt",
- ],
+ ["rfc-4231-sha256.txt"],
hashes.SHA256(),
)
@@ -88,9 +80,7 @@ class TestHMACSHA384(object):
test_hmac_sha384 = generate_hmac_test(
load_hash_vectors,
"HMAC",
- [
- "rfc-4231-sha384.txt",
- ],
+ ["rfc-4231-sha384.txt"],
hashes.SHA384(),
)
@@ -104,17 +94,15 @@ class TestHMACSHA512(object):
test_hmac_sha512 = generate_hmac_test(
load_hash_vectors,
"HMAC",
- [
- "rfc-4231-sha512.txt",
- ],
+ ["rfc-4231-sha512.txt"],
hashes.SHA512(),
)
@pytest.mark.supported(
- only_if=lambda backend: backend.hmac_supported(hashes.BLAKE2b(
- digest_size=64
- )),
+ only_if=lambda backend: backend.hmac_supported(
+ hashes.BLAKE2b(digest_size=64)
+ ),
skip_message="Does not support BLAKE2",
)
@pytest.mark.requires_backend_interface(interface=HMACBackend)
diff --git a/tests/hazmat/primitives/test_idea.py b/tests/hazmat/primitives/test_idea.py
index 75116dc18..1f766def0 100644
--- a/tests/hazmat/primitives/test_idea.py
+++ b/tests/hazmat/primitives/test_idea.py
@@ -24,7 +24,7 @@ from ...utils import load_nist_vectors
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestIDEAModeECB(object):
- test_ECB = generate_encrypt_test(
+ test_ecb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "IDEA"),
["idea-ecb.txt"],
@@ -41,12 +41,12 @@ class TestIDEAModeECB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestIDEAModeCBC(object):
- test_CBC = generate_encrypt_test(
+ test_cbc = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "IDEA"),
["idea-cbc.txt"],
lambda key, **kwargs: algorithms.IDEA(binascii.unhexlify((key))),
- lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv))
+ lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)),
)
@@ -58,12 +58,12 @@ class TestIDEAModeCBC(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestIDEAModeOFB(object):
- test_OFB = generate_encrypt_test(
+ test_ofb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "IDEA"),
["idea-ofb.txt"],
lambda key, **kwargs: algorithms.IDEA(binascii.unhexlify((key))),
- lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv))
+ lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv)),
)
@@ -75,10 +75,10 @@ class TestIDEAModeOFB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestIDEAModeCFB(object):
- test_CFB = generate_encrypt_test(
+ test_cfb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "IDEA"),
["idea-cfb.txt"],
lambda key, **kwargs: algorithms.IDEA(binascii.unhexlify((key))),
- lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv))
+ lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)),
)
diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py
index a16f1768d..5ff5d74ea 100644
--- a/tests/hazmat/primitives/test_kbkdf.py
+++ b/tests/hazmat/primitives/test_kbkdf.py
@@ -6,13 +6,13 @@ from __future__ import absolute_import, division, print_function
import pytest
-from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, _Reasons
-)
+from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.kbkdf import (
- CounterLocation, KBKDFHMAC, Mode
+ CounterLocation,
+ KBKDFHMAC,
+ Mode,
)
from ...doubles import DummyHashAlgorithm
@@ -22,137 +22,316 @@ from ...utils import raises_unsupported_algorithm
@pytest.mark.requires_backend_interface(interface=HMACBackend)
class TestKBKDFHMAC(object):
def test_invalid_key(self, backend):
- kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ kdf = KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
key = kdf.derive(b"material")
- kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ kdf = KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
with pytest.raises(InvalidKey):
kdf.verify(b"material2", key)
def test_already_finalized(self, backend):
- kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
-
- kdf.derive(b'material')
+ kdf = KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
+
+ kdf.derive(b"material")
with pytest.raises(AlreadyFinalized):
- kdf.derive(b'material2')
-
- kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ kdf.derive(b"material2")
+
+ kdf = KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
- key = kdf.derive(b'material')
+ key = kdf.derive(b"material")
with pytest.raises(AlreadyFinalized):
- kdf.verify(b'material', key)
+ kdf.verify(b"material", key)
- kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
- kdf.verify(b'material', key)
+ kdf = KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
+ kdf.verify(b"material", key)
with pytest.raises(AlreadyFinalized):
kdf.verify(b"material", key)
def test_key_length(self, backend):
- kdf = KBKDFHMAC(hashes.SHA1(), Mode.CounterMode, 85899345920, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ kdf = KBKDFHMAC(
+ hashes.SHA1(),
+ Mode.CounterMode,
+ 85899345920,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
with pytest.raises(ValueError):
- kdf.derive(b'material')
+ kdf.derive(b"material")
def test_rlen(self, backend):
with pytest.raises(ValueError):
- KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 5, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 5,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
def test_r_type(self, backend):
with pytest.raises(TypeError):
- KBKDFHMAC(hashes.SHA1(), Mode.CounterMode, 32, b'r', 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ KBKDFHMAC(
+ hashes.SHA1(),
+ Mode.CounterMode,
+ 32,
+ b"r",
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
def test_l_type(self, backend):
with pytest.raises(TypeError):
- KBKDFHMAC(hashes.SHA1(), Mode.CounterMode, 32, 4, b'l',
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ KBKDFHMAC(
+ hashes.SHA1(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ b"l",
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
def test_l(self, backend):
with pytest.raises(ValueError):
- KBKDFHMAC(hashes.SHA1(), Mode.CounterMode, 32, 4, None,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ KBKDFHMAC(
+ hashes.SHA1(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ None,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
def test_unsupported_mode(self, backend):
with pytest.raises(TypeError):
- KBKDFHMAC(hashes.SHA256(), None, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ KBKDFHMAC(
+ hashes.SHA256(),
+ None,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
def test_unsupported_location(self, backend):
with pytest.raises(TypeError):
- KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- None, b'label', b'context', None,
- backend=backend)
+ KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ None,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
def test_unsupported_parameters(self, backend):
with pytest.raises(ValueError):
- KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- b'fixed', backend=backend)
+ KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ b"fixed",
+ backend=backend,
+ )
def test_unsupported_hash(self, backend):
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH):
- KBKDFHMAC(object(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ KBKDFHMAC(
+ object(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
def test_unsupported_algorithm(self, backend):
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH):
- KBKDFHMAC(DummyHashAlgorithm(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ KBKDFHMAC(
+ DummyHashAlgorithm(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
def test_invalid_backend(self, backend):
with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
- KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=object())
+ KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=object(),
+ )
def test_unicode_error_label(self, backend):
with pytest.raises(TypeError):
- KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, u'label', b'context',
- backend=backend)
+ KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ u"label",
+ b"context",
+ backend=backend,
+ )
def test_unicode_error_context(self, backend):
with pytest.raises(TypeError):
- KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label', u'context',
- None, backend=backend)
+ KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ u"context",
+ None,
+ backend=backend,
+ )
def test_unicode_error_key_material(self, backend):
with pytest.raises(TypeError):
- kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 32, 4, 4,
- CounterLocation.BeforeFixed, b'label',
- b'context', None, backend=backend)
- kdf.derive(u'material')
+ kdf = KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 32,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
+ kdf.derive(u"material")
def test_buffer_protocol(self, backend):
- kdf = KBKDFHMAC(hashes.SHA256(), Mode.CounterMode, 10, 4, 4,
- CounterLocation.BeforeFixed, b'label', b'context',
- None, backend=backend)
+ kdf = KBKDFHMAC(
+ hashes.SHA256(),
+ Mode.CounterMode,
+ 10,
+ 4,
+ 4,
+ CounterLocation.BeforeFixed,
+ b"label",
+ b"context",
+ None,
+ backend=backend,
+ )
key = kdf.derive(bytearray(b"material"))
- assert key == b'\xb7\x01\x05\x98\xf5\x1a\x12L\xc7.'
+ assert key == b"\xb7\x01\x05\x98\xf5\x1a\x12L\xc7."
diff --git a/tests/hazmat/primitives/test_kbkdf_vectors.py b/tests/hazmat/primitives/test_kbkdf_vectors.py
index c8263e2b2..462e04ec5 100644
--- a/tests/hazmat/primitives/test_kbkdf_vectors.py
+++ b/tests/hazmat/primitives/test_kbkdf_vectors.py
@@ -16,8 +16,8 @@ from ...utils import load_nist_kbkdf_vectors
@pytest.mark.requires_backend_interface(interface=HMACBackend)
class TestCounterKDFCounterMode(object):
- test_HKDFSHA1 = generate_kbkdf_counter_mode_test(
+ test_kbkdfctr = generate_kbkdf_counter_mode_test(
load_nist_kbkdf_vectors,
os.path.join("KDF"),
- ["nist-800-108-KBKDF-CTR.txt"]
+ ["nist-800-108-KBKDF-CTR.txt"],
)
diff --git a/tests/hazmat/primitives/test_keywrap.py b/tests/hazmat/primitives/test_keywrap.py
index c74b144b6..9b91ccf36 100644
--- a/tests/hazmat/primitives/test_keywrap.py
+++ b/tests/hazmat/primitives/test_keywrap.py
@@ -24,15 +24,15 @@ class TestAESKeyWrap(object):
_load_all_params(
os.path.join("keywrap", "kwtestvectors"),
["KW_AE_128.txt", "KW_AE_192.txt", "KW_AE_256.txt"],
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
@pytest.mark.supported(
only_if=lambda backend: backend.cipher_supported(
algorithms.AES(b"\x00" * 16), modes.ECB()
),
skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
- " is unsupported",
+ " is unsupported",
)
def test_wrap(self, backend, params):
wrapping_key = binascii.unhexlify(params["k"])
@@ -45,15 +45,15 @@ class TestAESKeyWrap(object):
_load_all_params(
os.path.join("keywrap", "kwtestvectors"),
["KW_AD_128.txt", "KW_AD_192.txt", "KW_AD_256.txt"],
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
@pytest.mark.supported(
only_if=lambda backend: backend.cipher_supported(
algorithms.AES(b"\x00" * 16), modes.ECB()
),
skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
- " is unsupported",
+ " is unsupported",
)
def test_unwrap(self, backend, params):
wrapping_key = binascii.unhexlify(params["k"])
@@ -72,7 +72,7 @@ class TestAESKeyWrap(object):
algorithms.AES(b"\x00" * 16), modes.ECB()
),
skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
- " is unsupported",
+ " is unsupported",
)
def test_wrap_invalid_key_length(self, backend):
# The wrapping key must be of length [16, 24, 32]
@@ -84,7 +84,7 @@ class TestAESKeyWrap(object):
algorithms.AES(b"\x00" * 16), modes.ECB()
),
skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
- " is unsupported",
+ " is unsupported",
)
def test_unwrap_invalid_key_length(self, backend):
with pytest.raises(ValueError):
@@ -95,7 +95,7 @@ class TestAESKeyWrap(object):
algorithms.AES(b"\x00" * 16), modes.ECB()
),
skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
- " is unsupported",
+ " is unsupported",
)
def test_wrap_invalid_key_to_wrap_length(self, backend):
# Keys to wrap must be at least 16 bytes long
@@ -121,7 +121,7 @@ class TestAESKeyWrap(object):
algorithms.AES(b"\x00" * 16), modes.ECB()
),
skip_message="Does not support AES key wrap (RFC 5649) because AES-ECB"
- " is unsupported",
+ " is unsupported",
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestAESKeyWrapWithPadding(object):
@@ -130,8 +130,8 @@ class TestAESKeyWrapWithPadding(object):
_load_all_params(
os.path.join("keywrap", "kwtestvectors"),
["KWP_AE_128.txt", "KWP_AE_192.txt", "KWP_AE_256.txt"],
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_wrap(self, backend, params):
wrapping_key = binascii.unhexlify(params["k"])
@@ -143,7 +143,7 @@ class TestAESKeyWrapWithPadding(object):
@pytest.mark.parametrize(
"params",
- _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors)
+ _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors),
)
def test_wrap_additional_vectors(self, backend, params):
wrapping_key = binascii.unhexlify(params["key"])
@@ -158,8 +158,8 @@ class TestAESKeyWrapWithPadding(object):
_load_all_params(
os.path.join("keywrap", "kwtestvectors"),
["KWP_AD_128.txt", "KWP_AD_192.txt", "KWP_AD_256.txt"],
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_unwrap(self, backend, params):
wrapping_key = binascii.unhexlify(params["k"])
@@ -177,7 +177,7 @@ class TestAESKeyWrapWithPadding(object):
@pytest.mark.parametrize(
"params",
- _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors)
+ _load_all_params("keywrap", ["kwp_botan.txt"], load_nist_vectors),
)
def test_unwrap_additional_vectors(self, backend, params):
wrapping_key = binascii.unhexlify(params["key"])
@@ -190,18 +190,18 @@ class TestAESKeyWrapWithPadding(object):
def test_unwrap_invalid_wrapped_key_length(self, backend):
# Keys to unwrap must be at least 16 bytes
with pytest.raises(
- keywrap.InvalidUnwrap, match='Must be at least 16 bytes'
+ keywrap.InvalidUnwrap, match="Must be at least 16 bytes"
):
keywrap.aes_key_unwrap_with_padding(
b"sixteen_byte_key", b"\x00" * 15, backend
)
def test_wrap_invalid_key_length(self, backend):
- with pytest.raises(ValueError, match='must be a valid AES key length'):
+ with pytest.raises(ValueError, match="must be a valid AES key length"):
keywrap.aes_key_wrap_with_padding(b"badkey", b"\x00", backend)
def test_unwrap_invalid_key_length(self, backend):
- with pytest.raises(ValueError, match='must be a valid AES key length'):
+ with pytest.raises(ValueError, match="must be a valid AES key length"):
keywrap.aes_key_unwrap_with_padding(
b"badkey", b"\x00" * 16, backend
)
diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py
index fb72a794b..b15eb3753 100644
--- a/tests/hazmat/primitives/test_padding.py
+++ b/tests/hazmat/primitives/test_padding.py
@@ -18,14 +18,17 @@ class TestPKCS7(object):
with pytest.raises(ValueError):
padding.PKCS7(size)
- @pytest.mark.parametrize(("size", "padded"), [
- (128, b"1111"),
- (128, b"1111111111111111"),
- (128, b"111111111111111\x06"),
- (128, b""),
- (128, b"\x06" * 6),
- (128, b"\x00" * 16),
- ])
+ @pytest.mark.parametrize(
+ ("size", "padded"),
+ [
+ (128, b"1111"),
+ (128, b"1111111111111111"),
+ (128, b"111111111111111\x06"),
+ (128, b""),
+ (128, b"\x06" * 6),
+ (128, b"\x00" * 16),
+ ],
+ )
def test_invalid_padding(self, size, padded):
unpadder = padding.PKCS7(size).unpadder()
with pytest.raises(ValueError):
@@ -40,46 +43,48 @@ class TestPKCS7(object):
with pytest.raises(TypeError):
unpadder.update(u"abc")
- @pytest.mark.parametrize(("size", "unpadded", "padded"), [
- (
- 128,
- b"1111111111",
- b"1111111111\x06\x06\x06\x06\x06\x06",
- ),
- (
- 128,
- b"111111111111111122222222222222",
- b"111111111111111122222222222222\x02\x02",
- ),
- (
- 128,
- b"1" * 16,
- b"1" * 16 + b"\x10" * 16,
- ),
- (
- 128,
- b"1" * 17,
- b"1" * 17 + b"\x0F" * 15,
- )
- ])
+ def test_zany_py2_bytes_subclass(self):
+ class mybytes(bytes): # noqa: N801
+ def __str__(self):
+ return "broken"
+
+ str(mybytes())
+ padder = padding.PKCS7(128).padder()
+ padder.update(mybytes(b"abc"))
+ unpadder = padding.PKCS7(128).unpadder()
+ unpadder.update(mybytes(padder.finalize()))
+ assert unpadder.finalize() == b"abc"
+
+ @pytest.mark.parametrize(
+ ("size", "unpadded", "padded"),
+ [
+ (128, b"1111111111", b"1111111111\x06\x06\x06\x06\x06\x06"),
+ (
+ 128,
+ b"111111111111111122222222222222",
+ b"111111111111111122222222222222\x02\x02",
+ ),
+ (128, b"1" * 16, b"1" * 16 + b"\x10" * 16),
+ (128, b"1" * 17, b"1" * 17 + b"\x0F" * 15),
+ ],
+ )
def test_pad(self, size, unpadded, padded):
padder = padding.PKCS7(size).padder()
result = padder.update(unpadded)
result += padder.finalize()
assert result == padded
- @pytest.mark.parametrize(("size", "unpadded", "padded"), [
- (
- 128,
- b"1111111111",
- b"1111111111\x06\x06\x06\x06\x06\x06",
- ),
- (
- 128,
- b"111111111111111122222222222222",
- b"111111111111111122222222222222\x02\x02",
- ),
- ])
+ @pytest.mark.parametrize(
+ ("size", "unpadded", "padded"),
+ [
+ (128, b"1111111111", b"1111111111\x06\x06\x06\x06\x06\x06"),
+ (
+ 128,
+ b"111111111111111122222222222222",
+ b"111111111111111122222222222222\x02\x02",
+ ),
+ ],
+ )
def test_unpad(self, size, unpadded, padded):
unpadder = padding.PKCS7(size).unpadder()
result = unpadder.update(padded)
@@ -116,6 +121,18 @@ class TestPKCS7(object):
assert data == b""
+ def test_bytearray(self):
+ padder = padding.PKCS7(128).padder()
+ unpadded = bytearray(b"t" * 38)
+ padded = (
+ padder.update(unpadded)
+ + padder.update(unpadded)
+ + padder.finalize()
+ )
+ unpadder = padding.PKCS7(128).unpadder()
+ final = unpadder.update(padded) + unpadder.finalize()
+ assert final == unpadded + unpadded
+
class TestANSIX923(object):
@pytest.mark.parametrize("size", [127, 4096, -2])
@@ -123,15 +140,18 @@ class TestANSIX923(object):
with pytest.raises(ValueError):
padding.ANSIX923(size)
- @pytest.mark.parametrize(("size", "padded"), [
- (128, b"1111"),
- (128, b"1111111111111111"),
- (128, b"111111111111111\x06"),
- (128, b"1111111111\x06\x06\x06\x06\x06\x06"),
- (128, b""),
- (128, b"\x06" * 6),
- (128, b"\x00" * 16),
- ])
+ @pytest.mark.parametrize(
+ ("size", "padded"),
+ [
+ (128, b"1111"),
+ (128, b"1111111111111111"),
+ (128, b"111111111111111\x06"),
+ (128, b"1111111111\x06\x06\x06\x06\x06\x06"),
+ (128, b""),
+ (128, b"\x06" * 6),
+ (128, b"\x00" * 16),
+ ],
+ )
def test_invalid_padding(self, size, padded):
unpadder = padding.ANSIX923(size).unpadder()
with pytest.raises(ValueError):
@@ -146,46 +166,48 @@ class TestANSIX923(object):
with pytest.raises(TypeError):
unpadder.update(u"abc")
- @pytest.mark.parametrize(("size", "unpadded", "padded"), [
- (
- 128,
- b"1111111111",
- b"1111111111\x00\x00\x00\x00\x00\x06",
- ),
- (
- 128,
- b"111111111111111122222222222222",
- b"111111111111111122222222222222\x00\x02",
- ),
- (
- 128,
- b"1" * 16,
- b"1" * 16 + b"\x00" * 15 + b"\x10",
- ),
- (
- 128,
- b"1" * 17,
- b"1" * 17 + b"\x00" * 14 + b"\x0F",
- )
- ])
+ def test_zany_py2_bytes_subclass(self):
+ class mybytes(bytes): # noqa: N801
+ def __str__(self):
+ return "broken"
+
+ str(mybytes())
+ padder = padding.ANSIX923(128).padder()
+ padder.update(mybytes(b"abc"))
+ unpadder = padding.ANSIX923(128).unpadder()
+ unpadder.update(mybytes(padder.finalize()))
+ assert unpadder.finalize() == b"abc"
+
+ @pytest.mark.parametrize(
+ ("size", "unpadded", "padded"),
+ [
+ (128, b"1111111111", b"1111111111\x00\x00\x00\x00\x00\x06"),
+ (
+ 128,
+ b"111111111111111122222222222222",
+ b"111111111111111122222222222222\x00\x02",
+ ),
+ (128, b"1" * 16, b"1" * 16 + b"\x00" * 15 + b"\x10"),
+ (128, b"1" * 17, b"1" * 17 + b"\x00" * 14 + b"\x0F"),
+ ],
+ )
def test_pad(self, size, unpadded, padded):
padder = padding.ANSIX923(size).padder()
result = padder.update(unpadded)
result += padder.finalize()
assert result == padded
- @pytest.mark.parametrize(("size", "unpadded", "padded"), [
- (
- 128,
- b"1111111111",
- b"1111111111\x00\x00\x00\x00\x00\x06",
- ),
- (
- 128,
- b"111111111111111122222222222222",
- b"111111111111111122222222222222\x00\x02",
- ),
- ])
+ @pytest.mark.parametrize(
+ ("size", "unpadded", "padded"),
+ [
+ (128, b"1111111111", b"1111111111\x00\x00\x00\x00\x00\x06"),
+ (
+ 128,
+ b"111111111111111122222222222222",
+ b"111111111111111122222222222222\x00\x02",
+ ),
+ ],
+ )
def test_unpad(self, size, unpadded, padded):
unpadder = padding.ANSIX923(size).unpadder()
result = unpadder.update(padded)
@@ -207,3 +229,15 @@ class TestANSIX923(object):
unpadder.update(b"")
with pytest.raises(AlreadyFinalized):
unpadder.finalize()
+
+ def test_bytearray(self):
+ padder = padding.ANSIX923(128).padder()
+ unpadded = bytearray(b"t" * 38)
+ padded = (
+ padder.update(unpadded)
+ + padder.update(unpadded)
+ + padder.finalize()
+ )
+ unpadder = padding.ANSIX923(128).unpadder()
+ final = unpadder.update(padded) + unpadder.finalize()
+ assert final == unpadded + unpadded
diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py
index 0254b2168..34fd25cf4 100644
--- a/tests/hazmat/primitives/test_pbkdf2hmac.py
+++ b/tests/hazmat/primitives/test_pbkdf2hmac.py
@@ -6,10 +6,7 @@ from __future__ import absolute_import, division, print_function
import pytest
-from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, _Reasons
-)
-from cryptography.hazmat.backends import default_backend
+from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
@@ -18,47 +15,45 @@ from ...utils import raises_unsupported_algorithm
class TestPBKDF2HMAC(object):
- def test_already_finalized(self):
- kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ def test_already_finalized(self, backend):
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
kdf.derive(b"password")
with pytest.raises(AlreadyFinalized):
kdf.derive(b"password2")
- kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
key = kdf.derive(b"password")
with pytest.raises(AlreadyFinalized):
kdf.verify(b"password", key)
- kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
kdf.verify(b"password", key)
with pytest.raises(AlreadyFinalized):
kdf.verify(b"password", key)
- def test_unsupported_algorithm(self):
+ def test_unsupported_algorithm(self, backend):
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH):
- PBKDF2HMAC(
- DummyHashAlgorithm(), 20, b"salt", 10, default_backend()
- )
+ PBKDF2HMAC(DummyHashAlgorithm(), 20, b"salt", 10, backend)
- def test_invalid_key(self):
- kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ def test_invalid_key(self, backend):
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
key = kdf.derive(b"password")
- kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
with pytest.raises(InvalidKey):
kdf.verify(b"password2", key)
- def test_unicode_error_with_salt(self):
+ def test_unicode_error_with_salt(self, backend):
with pytest.raises(TypeError):
- PBKDF2HMAC(hashes.SHA1(), 20, u"salt", 10, default_backend())
+ PBKDF2HMAC(hashes.SHA1(), 20, u"salt", 10, backend)
- def test_unicode_error_with_key_material(self):
- kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, default_backend())
+ def test_unicode_error_with_key_material(self, backend):
+ kdf = PBKDF2HMAC(hashes.SHA1(), 20, b"salt", 10, backend)
with pytest.raises(TypeError):
kdf.derive(u"unicode here")
def test_buffer_protocol(self, backend):
- kdf = PBKDF2HMAC(hashes.SHA1(), 10, b"salt", 10, default_backend())
+ kdf = PBKDF2HMAC(hashes.SHA1(), 10, b"salt", 10, backend)
data = bytearray(b"data")
assert kdf.derive(data) == b"\xe9n\xaa\x81\xbbt\xa4\xf6\x08\xce"
diff --git a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
index fe51f5438..4b97b0d13 100644
--- a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
+++ b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py
@@ -22,8 +22,6 @@ class TestPBKDF2HMACSHA1(object):
test_pbkdf2_sha1 = generate_pbkdf2_test(
load_nist_vectors,
"KDF",
- [
- "rfc-6070-PBKDF2-SHA1.txt",
- ],
+ ["rfc-6070-PBKDF2-SHA1.txt"],
hashes.SHA1(),
)
diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py
index f084d578c..297483e2f 100644
--- a/tests/hazmat/primitives/test_pkcs12.py
+++ b/tests/hazmat/primitives/test_pkcs12.py
@@ -10,61 +10,85 @@ import pytest
from cryptography import x509
from cryptography.hazmat.backends.interfaces import DERSerializationBackend
+from cryptography.hazmat.backends.openssl.backend import _RC2
+from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.primitives.serialization.pkcs12 import (
- load_key_and_certificates
+ load_key_and_certificates,
+ serialize_key_and_certificates,
)
from .utils import load_vectors_from_file
+from ...doubles import DummyKeySerializationEncryption
@pytest.mark.requires_backend_interface(interface=DERSerializationBackend)
-class TestPKCS12(object):
- @pytest.mark.parametrize(
- ("filename", "password"),
- [
- ("cert-key-aes256cbc.p12", b"cryptography"),
- ("cert-none-key-none.p12", b"cryptography"),
- ("cert-rc2-key-3des.p12", b"cryptography"),
- ("no-password.p12", None),
- ]
- )
- def test_load_pkcs12_ec_keys(self, filename, password, backend):
+class TestPKCS12Loading(object):
+ def _test_load_pkcs12_ec_keys(self, filename, password, backend):
cert = load_vectors_from_file(
os.path.join("x509", "custom", "ca", "ca.pem"),
lambda pemfile: x509.load_pem_x509_certificate(
pemfile.read(), backend
- ), mode="rb"
+ ),
+ mode="rb",
)
key = load_vectors_from_file(
os.path.join("x509", "custom", "ca", "ca_key.pem"),
lambda pemfile: load_pem_private_key(
pemfile.read(), None, backend
- ), mode="rb"
+ ),
+ mode="rb",
)
parsed_key, parsed_cert, parsed_more_certs = load_vectors_from_file(
os.path.join("pkcs12", filename),
lambda derfile: load_key_and_certificates(
derfile.read(), password, backend
- ), mode="rb"
+ ),
+ mode="rb",
)
assert parsed_cert == cert
assert parsed_key.private_numbers() == key.private_numbers()
assert parsed_more_certs == []
+ @pytest.mark.parametrize(
+ ("filename", "password"),
+ [
+ ("cert-key-aes256cbc.p12", b"cryptography"),
+ ("cert-none-key-none.p12", b"cryptography"),
+ ],
+ )
+ def test_load_pkcs12_ec_keys(self, filename, password, backend):
+ self._test_load_pkcs12_ec_keys(filename, password, backend)
+
+ @pytest.mark.parametrize(
+ ("filename", "password"),
+ [
+ ("cert-rc2-key-3des.p12", b"cryptography"),
+ ("no-password.p12", None),
+ ],
+ )
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(_RC2(), None),
+ skip_message="Does not support RC2",
+ )
+ @pytest.mark.skip_fips(reason="Unsupported algorithm in FIPS mode")
+ def test_load_pkcs12_ec_keys_rc2(self, filename, password, backend):
+ self._test_load_pkcs12_ec_keys(filename, password, backend)
+
def test_load_pkcs12_cert_only(self, backend):
cert = load_vectors_from_file(
os.path.join("x509", "custom", "ca", "ca.pem"),
lambda pemfile: x509.load_pem_x509_certificate(
pemfile.read(), backend
- ), mode="rb"
+ ),
+ mode="rb",
)
parsed_key, parsed_cert, parsed_more_certs = load_vectors_from_file(
os.path.join("pkcs12", "cert-aes256cbc-no-key.p12"),
lambda data: load_key_and_certificates(
data.read(), b"cryptography", backend
),
- mode="rb"
+ mode="rb",
)
assert parsed_cert is None
assert parsed_key is None
@@ -75,14 +99,15 @@ class TestPKCS12(object):
os.path.join("x509", "custom", "ca", "ca_key.pem"),
lambda pemfile: load_pem_private_key(
pemfile.read(), None, backend
- ), mode="rb"
+ ),
+ mode="rb",
)
parsed_key, parsed_cert, parsed_more_certs = load_vectors_from_file(
os.path.join("pkcs12", "no-cert-key-aes256cbc.p12"),
lambda data: load_key_and_certificates(
data.read(), b"cryptography", backend
),
- mode="rb"
+ mode="rb",
)
assert parsed_key.private_numbers() == key.private_numbers()
assert parsed_cert is None
@@ -90,15 +115,11 @@ class TestPKCS12(object):
def test_non_bytes(self, backend):
with pytest.raises(TypeError):
- load_key_and_certificates(
- b"irrelevant", object(), backend
- )
+ load_key_and_certificates(b"irrelevant", object(), backend)
def test_not_a_pkcs12(self, backend):
with pytest.raises(ValueError):
- load_key_and_certificates(
- b"invalid", b"pass", backend
- )
+ load_key_and_certificates(b"invalid", b"pass", backend)
def test_invalid_password(self, backend):
with pytest.raises(ValueError):
@@ -106,13 +127,15 @@ class TestPKCS12(object):
os.path.join("pkcs12", "cert-key-aes256cbc.p12"),
lambda derfile: load_key_and_certificates(
derfile.read(), b"invalid", backend
- ), mode="rb"
+ ),
+ mode="rb",
)
def test_buffer_protocol(self, backend):
p12 = load_vectors_from_file(
os.path.join("pkcs12", "cert-key-aes256cbc.p12"),
- lambda derfile: derfile.read(), mode="rb"
+ lambda derfile: derfile.read(),
+ mode="rb",
)
p12buffer = bytearray(p12)
parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates(
@@ -121,3 +144,128 @@ class TestPKCS12(object):
assert parsed_key is not None
assert parsed_cert is not None
assert parsed_more_certs == []
+
+
+def _load_cert(backend, path):
+ return load_vectors_from_file(
+ path,
+ lambda pemfile: x509.load_pem_x509_certificate(
+ pemfile.read(), backend
+ ),
+ mode="rb",
+ )
+
+
+def _load_ca(backend):
+ cert = _load_cert(backend, os.path.join("x509", "custom", "ca", "ca.pem"))
+ key = load_vectors_from_file(
+ os.path.join("x509", "custom", "ca", "ca_key.pem"),
+ lambda pemfile: load_pem_private_key(pemfile.read(), None, backend),
+ mode="rb",
+ )
+ return cert, key
+
+
+class TestPKCS12Creation(object):
+ @pytest.mark.parametrize("name", [None, b"name"])
+ @pytest.mark.parametrize(
+ ("encryption_algorithm", "password"),
+ [
+ (serialization.BestAvailableEncryption(b"password"), b"password"),
+ (serialization.NoEncryption(), None),
+ ],
+ )
+ def test_generate(self, backend, name, encryption_algorithm, password):
+ cert, key = _load_ca(backend)
+ p12 = serialize_key_and_certificates(
+ name, key, cert, None, encryption_algorithm
+ )
+
+ parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates(
+ p12, password, backend
+ )
+ assert parsed_cert == cert
+ assert parsed_key.private_numbers() == key.private_numbers()
+ assert parsed_more_certs == []
+
+ def test_generate_with_cert_key_ca(self, backend):
+ cert, key = _load_ca(backend)
+ cert2 = _load_cert(
+ backend, os.path.join("x509", "custom", "dsa_selfsigned_ca.pem")
+ )
+ cert3 = _load_cert(backend, os.path.join("x509", "letsencryptx3.pem"))
+ encryption = serialization.NoEncryption()
+ p12 = serialize_key_and_certificates(
+ None, key, cert, [cert2, cert3], encryption
+ )
+
+ parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates(
+ p12, None, backend
+ )
+ assert parsed_cert == cert
+ assert parsed_key.private_numbers() == key.private_numbers()
+ assert parsed_more_certs == [cert2, cert3]
+
+ def test_generate_wrong_types(self, backend):
+ cert, key = _load_ca(backend)
+ cert2 = _load_cert(backend, os.path.join("x509", "letsencryptx3.pem"))
+ encryption = serialization.NoEncryption()
+ with pytest.raises(TypeError) as exc:
+ serialize_key_and_certificates(
+ b"name", cert, cert, None, encryption
+ )
+ assert (
+ str(exc.value)
+ == "Key must be RSA, DSA, or EllipticCurve private key."
+ )
+
+ with pytest.raises(TypeError) as exc:
+ serialize_key_and_certificates(b"name", key, key, None, encryption)
+ assert str(exc.value) == "cert must be a certificate"
+
+ with pytest.raises(TypeError) as exc:
+ serialize_key_and_certificates(b"name", key, cert, None, key)
+ assert str(exc.value) == (
+ "Key encryption algorithm must be a "
+ "KeySerializationEncryption instance"
+ )
+
+ with pytest.raises(TypeError) as exc:
+ serialize_key_and_certificates(None, key, cert, cert2, encryption)
+
+ with pytest.raises(TypeError) as exc:
+ serialize_key_and_certificates(None, key, cert, [key], encryption)
+ assert str(exc.value) == "all values in cas must be certificates"
+
+ def test_generate_no_cert(self, backend):
+ _, key = _load_ca(backend)
+ p12 = serialize_key_and_certificates(
+ None, key, None, None, serialization.NoEncryption()
+ )
+ parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates(
+ p12, None, backend
+ )
+ assert parsed_cert is None
+ assert parsed_key.private_numbers() == key.private_numbers()
+ assert parsed_more_certs == []
+
+ def test_must_supply_something(self):
+ with pytest.raises(ValueError) as exc:
+ serialize_key_and_certificates(
+ None, None, None, None, serialization.NoEncryption()
+ )
+ assert str(exc.value) == (
+ "You must supply at least one of key, cert, or cas"
+ )
+
+ def test_generate_unsupported_encryption_type(self, backend):
+ cert, key = _load_ca(backend)
+ with pytest.raises(ValueError) as exc:
+ serialize_key_and_certificates(
+ None,
+ key,
+ cert,
+ None,
+ DummyKeySerializationEncryption(),
+ )
+ assert str(exc.value) == "Unsupported key encryption type"
diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py
new file mode 100644
index 000000000..8b93cb633
--- /dev/null
+++ b/tests/hazmat/primitives/test_pkcs7.py
@@ -0,0 +1,675 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import os
+
+import pytest
+
+from cryptography import x509
+from cryptography.exceptions import _Reasons
+from cryptography.hazmat.primitives import hashes, serialization
+from cryptography.hazmat.primitives.asymmetric import ed25519
+from cryptography.hazmat.primitives.serialization import pkcs7
+
+from .utils import load_vectors_from_file
+from ...utils import raises_unsupported_algorithm
+
+
+class TestPKCS7Loading(object):
+ def test_load_invalid_der_pkcs7(self):
+ with pytest.raises(ValueError):
+ pkcs7.load_der_pkcs7_certificates(b"nonsense")
+
+ def test_load_invalid_pem_pkcs7(self):
+ with pytest.raises(ValueError):
+ pkcs7.load_pem_pkcs7_certificates(b"nonsense")
+
+ def test_not_bytes_der(self):
+ with pytest.raises(TypeError):
+ pkcs7.load_der_pkcs7_certificates(38)
+
+ def test_not_bytes_pem(self):
+ with pytest.raises(TypeError):
+ pkcs7.load_pem_pkcs7_certificates(38)
+
+ def test_load_pkcs7_pem(self):
+ certs = load_vectors_from_file(
+ os.path.join("pkcs7", "isrg.pem"),
+ lambda pemfile: pkcs7.load_pem_pkcs7_certificates(pemfile.read()),
+ mode="rb",
+ )
+ assert len(certs) == 1
+ assert certs[0].subject.get_attributes_for_oid(
+ x509.oid.NameOID.COMMON_NAME
+ ) == [
+ x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, u"ISRG Root X1")
+ ]
+
+ def test_load_pkcs7_der(self):
+ certs = load_vectors_from_file(
+ os.path.join("pkcs7", "amazon-roots.p7b"),
+ lambda derfile: pkcs7.load_der_pkcs7_certificates(derfile.read()),
+ mode="rb",
+ )
+ assert len(certs) == 2
+ assert certs[0].subject.get_attributes_for_oid(
+ x509.oid.NameOID.COMMON_NAME
+ ) == [
+ x509.NameAttribute(
+ x509.oid.NameOID.COMMON_NAME, u"Amazon Root CA 3"
+ )
+ ]
+ assert certs[1].subject.get_attributes_for_oid(
+ x509.oid.NameOID.COMMON_NAME
+ ) == [
+ x509.NameAttribute(
+ x509.oid.NameOID.COMMON_NAME, u"Amazon Root CA 2"
+ )
+ ]
+
+ def test_load_pkcs7_unsupported_type(self):
+ with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
+ load_vectors_from_file(
+ os.path.join("pkcs7", "enveloped.pem"),
+ lambda pemfile: pkcs7.load_pem_pkcs7_certificates(
+ pemfile.read()
+ ),
+ mode="rb",
+ )
+
+
+# We have no public verification API and won't be adding one until we get
+# some requirements from users so this function exists to give us basic
+# verification for the signing tests.
+def _pkcs7_verify(encoding, sig, msg, certs, options, backend):
+ sig_bio = backend._bytes_to_bio(sig)
+ if encoding is serialization.Encoding.DER:
+ p7 = backend._lib.d2i_PKCS7_bio(sig_bio.bio, backend._ffi.NULL)
+ elif encoding is serialization.Encoding.PEM:
+ p7 = backend._lib.PEM_read_bio_PKCS7(
+ sig_bio.bio,
+ backend._ffi.NULL,
+ backend._ffi.NULL,
+ backend._ffi.NULL,
+ )
+ else:
+ p7 = backend._lib.SMIME_read_PKCS7(sig_bio.bio, backend._ffi.NULL)
+ backend.openssl_assert(p7 != backend._ffi.NULL)
+ p7 = backend._ffi.gc(p7, backend._lib.PKCS7_free)
+ flags = 0
+ for option in options:
+ if option is pkcs7.PKCS7Options.Text:
+ flags |= backend._lib.PKCS7_TEXT
+ store = backend._lib.X509_STORE_new()
+ backend.openssl_assert(store != backend._ffi.NULL)
+ store = backend._ffi.gc(store, backend._lib.X509_STORE_free)
+ for cert in certs:
+ res = backend._lib.X509_STORE_add_cert(store, cert._x509)
+ backend.openssl_assert(res == 1)
+ if msg is None:
+ res = backend._lib.PKCS7_verify(
+ p7,
+ backend._ffi.NULL,
+ store,
+ backend._ffi.NULL,
+ backend._ffi.NULL,
+ flags,
+ )
+ else:
+ msg_bio = backend._bytes_to_bio(msg)
+ res = backend._lib.PKCS7_verify(
+ p7, backend._ffi.NULL, store, msg_bio.bio, backend._ffi.NULL, flags
+ )
+ backend.openssl_assert(res == 1)
+
+
+def _load_cert_key():
+ key = load_vectors_from_file(
+ os.path.join("x509", "custom", "ca", "ca_key.pem"),
+ lambda pemfile: serialization.load_pem_private_key(
+ pemfile.read(), None
+ ),
+ mode="rb",
+ )
+ cert = load_vectors_from_file(
+ os.path.join("x509", "custom", "ca", "ca.pem"),
+ loader=lambda pemfile: x509.load_pem_x509_certificate(pemfile.read()),
+ mode="rb",
+ )
+ return cert, key
+
+
+class TestPKCS7Builder(object):
+ def test_invalid_data(self):
+ builder = pkcs7.PKCS7SignatureBuilder()
+ with pytest.raises(TypeError):
+ builder.set_data(u"not bytes")
+
+ def test_set_data_twice(self):
+ builder = pkcs7.PKCS7SignatureBuilder().set_data(b"test")
+ with pytest.raises(ValueError):
+ builder.set_data(b"test")
+
+ def test_sign_no_signer(self):
+ builder = pkcs7.PKCS7SignatureBuilder().set_data(b"test")
+ with pytest.raises(ValueError):
+ builder.sign(serialization.Encoding.SMIME, [])
+
+ def test_sign_no_data(self):
+ cert, key = _load_cert_key()
+ builder = pkcs7.PKCS7SignatureBuilder().add_signer(
+ cert, key, hashes.SHA256()
+ )
+ with pytest.raises(ValueError):
+ builder.sign(serialization.Encoding.SMIME, [])
+
+ def test_unsupported_hash_alg(self):
+ cert, key = _load_cert_key()
+ with pytest.raises(TypeError):
+ pkcs7.PKCS7SignatureBuilder().add_signer(
+ cert, key, hashes.SHA512_256()
+ )
+
+ def test_not_a_cert(self):
+ cert, key = _load_cert_key()
+ with pytest.raises(TypeError):
+ pkcs7.PKCS7SignatureBuilder().add_signer(
+ b"notacert", key, hashes.SHA256()
+ )
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Does not support ed25519.",
+ )
+ def test_unsupported_key_type(self, backend):
+ cert, _ = _load_cert_key()
+ key = ed25519.Ed25519PrivateKey.generate()
+ with pytest.raises(TypeError):
+ pkcs7.PKCS7SignatureBuilder().add_signer(
+ cert, key, hashes.SHA256()
+ )
+
+ def test_sign_invalid_options(self):
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(b"test")
+ .add_signer(cert, key, hashes.SHA256())
+ )
+ with pytest.raises(ValueError):
+ builder.sign(serialization.Encoding.SMIME, [b"invalid"])
+
+ def test_sign_invalid_encoding(self):
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(b"test")
+ .add_signer(cert, key, hashes.SHA256())
+ )
+ with pytest.raises(ValueError):
+ builder.sign(serialization.Encoding.Raw, [])
+
+ def test_sign_invalid_options_text_no_detached(self):
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(b"test")
+ .add_signer(cert, key, hashes.SHA256())
+ )
+ options = [pkcs7.PKCS7Options.Text]
+ with pytest.raises(ValueError):
+ builder.sign(serialization.Encoding.SMIME, options)
+
+ def test_sign_invalid_options_text_der_encoding(self):
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(b"test")
+ .add_signer(cert, key, hashes.SHA256())
+ )
+ options = [
+ pkcs7.PKCS7Options.Text,
+ pkcs7.PKCS7Options.DetachedSignature,
+ ]
+ with pytest.raises(ValueError):
+ builder.sign(serialization.Encoding.DER, options)
+
+ def test_sign_invalid_options_no_attrs_and_no_caps(self):
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(b"test")
+ .add_signer(cert, key, hashes.SHA256())
+ )
+ options = [
+ pkcs7.PKCS7Options.NoAttributes,
+ pkcs7.PKCS7Options.NoCapabilities,
+ ]
+ with pytest.raises(ValueError):
+ builder.sign(serialization.Encoding.SMIME, options)
+
+ def test_smime_sign_detached(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ options = [pkcs7.PKCS7Options.DetachedSignature]
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+
+ sig = builder.sign(serialization.Encoding.SMIME, options)
+ sig_binary = builder.sign(serialization.Encoding.DER, options)
+ # We don't have a generic ASN.1 parser available to us so we instead
+ # will assert on specific byte sequences being present based on the
+ # parameters chosen above.
+ assert b"sha-256" in sig
+ # Detached signature means that the signed data is *not* embedded into
+ # the PKCS7 structure itself, but is present in the SMIME serialization
+ # as a separate section before the PKCS7 data. So we should expect to
+ # have data in sig but not in sig_binary
+ assert data in sig
+ _pkcs7_verify(
+ serialization.Encoding.SMIME, sig, data, [cert], options, backend
+ )
+ assert data not in sig_binary
+ _pkcs7_verify(
+ serialization.Encoding.DER,
+ sig_binary,
+ data,
+ [cert],
+ options,
+ backend,
+ )
+
+ def test_sign_byteslike(self):
+ data = bytearray(b"hello world")
+ cert, key = _load_cert_key()
+ options = [pkcs7.PKCS7Options.DetachedSignature]
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+
+ sig = builder.sign(serialization.Encoding.SMIME, options)
+ assert bytes(data) in sig
+
+ def test_sign_pem(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ options = []
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+
+ sig = builder.sign(serialization.Encoding.PEM, options)
+ _pkcs7_verify(
+ serialization.Encoding.PEM,
+ sig,
+ None,
+ [cert],
+ options,
+ backend,
+ )
+
+ @pytest.mark.parametrize(
+ ("hash_alg", "expected_value"),
+ [
+ (hashes.SHA1(), b"\x06\x05+\x0e\x03\x02\x1a"),
+ (hashes.SHA256(), b"\x06\t`\x86H\x01e\x03\x04\x02\x01"),
+ (hashes.SHA384(), b"\x06\t`\x86H\x01e\x03\x04\x02\x02"),
+ (hashes.SHA512(), b"\x06\t`\x86H\x01e\x03\x04\x02\x03"),
+ ],
+ )
+ def test_sign_alternate_digests_der(
+ self, hash_alg, expected_value, backend
+ ):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hash_alg)
+ )
+ options = []
+ sig = builder.sign(serialization.Encoding.DER, options)
+ assert expected_value in sig
+ _pkcs7_verify(
+ serialization.Encoding.DER, sig, None, [cert], options, backend
+ )
+
+ @pytest.mark.parametrize(
+ ("hash_alg", "expected_value"),
+ [
+ (hashes.SHA1(), b"sha1"),
+ (hashes.SHA256(), b"sha-256"),
+ (hashes.SHA384(), b"sha-384"),
+ (hashes.SHA512(), b"sha-512"),
+ ],
+ )
+ def test_sign_alternate_digests_detached(self, hash_alg, expected_value):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hash_alg)
+ )
+ options = [pkcs7.PKCS7Options.DetachedSignature]
+ sig = builder.sign(serialization.Encoding.SMIME, options)
+ # When in detached signature mode the hash algorithm is stored as a
+ # byte string like "sha-384".
+ assert expected_value in sig
+
+ def test_sign_attached(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ options = []
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+
+ sig_binary = builder.sign(serialization.Encoding.DER, options)
+ # When not passing detached signature the signed data is embedded into
+ # the PKCS7 structure itself
+ assert data in sig_binary
+ _pkcs7_verify(
+ serialization.Encoding.DER,
+ sig_binary,
+ None,
+ [cert],
+ options,
+ backend,
+ )
+
+ def test_sign_binary(self, backend):
+ data = b"hello\nworld"
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+ options = []
+ sig_no_binary = builder.sign(serialization.Encoding.DER, options)
+ sig_binary = builder.sign(
+ serialization.Encoding.DER, [pkcs7.PKCS7Options.Binary]
+ )
+ # Binary prevents translation of LF to CR+LF (SMIME canonical form)
+ # so data should not be present in sig_no_binary, but should be present
+ # in sig_binary
+ assert data not in sig_no_binary
+ _pkcs7_verify(
+ serialization.Encoding.DER,
+ sig_no_binary,
+ None,
+ [cert],
+ options,
+ backend,
+ )
+ assert data in sig_binary
+ _pkcs7_verify(
+ serialization.Encoding.DER,
+ sig_binary,
+ None,
+ [cert],
+ options,
+ backend,
+ )
+
+ def test_sign_smime_canonicalization(self, backend):
+ data = b"hello\nworld"
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+
+ options = []
+ sig_binary = builder.sign(serialization.Encoding.DER, options)
+ # LF gets converted to CR+LF (SMIME canonical form)
+ # so data should not be present in the sig
+ assert data not in sig_binary
+ assert b"hello\r\nworld" in sig_binary
+ _pkcs7_verify(
+ serialization.Encoding.DER,
+ sig_binary,
+ None,
+ [cert],
+ options,
+ backend,
+ )
+
+ def test_sign_text(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+
+ options = [
+ pkcs7.PKCS7Options.Text,
+ pkcs7.PKCS7Options.DetachedSignature,
+ ]
+ sig_pem = builder.sign(serialization.Encoding.SMIME, options)
+ # The text option adds text/plain headers to the S/MIME message
+ # These headers are only relevant in SMIME mode, not binary, which is
+ # just the PKCS7 structure itself.
+ assert b"text/plain" in sig_pem
+ # When passing the Text option the header is prepended so the actual
+ # signed data is this.
+ signed_data = b"Content-Type: text/plain\r\n\r\nhello world"
+ _pkcs7_verify(
+ serialization.Encoding.SMIME,
+ sig_pem,
+ signed_data,
+ [cert],
+ options,
+ backend,
+ )
+
+ def test_sign_no_capabilities(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+
+ options = [pkcs7.PKCS7Options.NoCapabilities]
+ sig_binary = builder.sign(serialization.Encoding.DER, options)
+ # NoCapabilities removes the SMIMECapabilities attribute from the
+ # PKCS7 structure. This is an ASN.1 sequence with the
+ # OID 1.2.840.113549.1.9.15. It does NOT remove all authenticated
+ # attributes, so we verify that by looking for the signingTime OID.
+
+ # 1.2.840.113549.1.9.15 SMIMECapabilities as an ASN.1 DER encoded OID
+ assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x0f" not in sig_binary
+ # 1.2.840.113549.1.9.5 signingTime as an ASN.1 DER encoded OID
+ assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x05" in sig_binary
+ _pkcs7_verify(
+ serialization.Encoding.DER,
+ sig_binary,
+ None,
+ [cert],
+ options,
+ backend,
+ )
+
+ def test_sign_no_attributes(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+
+ options = [pkcs7.PKCS7Options.NoAttributes]
+ sig_binary = builder.sign(serialization.Encoding.DER, options)
+ # NoAttributes removes all authenticated attributes, so we shouldn't
+ # find SMIMECapabilities or signingTime.
+
+ # 1.2.840.113549.1.9.15 SMIMECapabilities as an ASN.1 DER encoded OID
+ assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x0f" not in sig_binary
+ # 1.2.840.113549.1.9.5 signingTime as an ASN.1 DER encoded OID
+ assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x05" not in sig_binary
+ _pkcs7_verify(
+ serialization.Encoding.DER,
+ sig_binary,
+ None,
+ [cert],
+ options,
+ backend,
+ )
+
+ def test_sign_no_certs(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA256())
+ )
+
+ options = []
+ sig = builder.sign(serialization.Encoding.DER, options)
+ assert sig.count(cert.public_bytes(serialization.Encoding.DER)) == 1
+
+ options = [pkcs7.PKCS7Options.NoCerts]
+ sig_no = builder.sign(serialization.Encoding.DER, options)
+ assert sig_no.count(cert.public_bytes(serialization.Encoding.DER)) == 0
+
+ def test_multiple_signers(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ rsa_key = load_vectors_from_file(
+ os.path.join("x509", "custom", "ca", "rsa_key.pem"),
+ lambda pemfile: serialization.load_pem_private_key(
+ pemfile.read(), None
+ ),
+ mode="rb",
+ )
+ rsa_cert = load_vectors_from_file(
+ os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
+ loader=lambda pemfile: x509.load_pem_x509_certificate(
+ pemfile.read()
+ ),
+ mode="rb",
+ )
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA512())
+ .add_signer(rsa_cert, rsa_key, hashes.SHA512())
+ )
+ options = []
+ sig = builder.sign(serialization.Encoding.DER, options)
+ # There should be three SHA512 OIDs in this structure
+ assert sig.count(b"\x06\t`\x86H\x01e\x03\x04\x02\x03") == 3
+ _pkcs7_verify(
+ serialization.Encoding.DER,
+ sig,
+ None,
+ [cert, rsa_cert],
+ options,
+ backend,
+ )
+
+ def test_multiple_signers_different_hash_algs(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ rsa_key = load_vectors_from_file(
+ os.path.join("x509", "custom", "ca", "rsa_key.pem"),
+ lambda pemfile: serialization.load_pem_private_key(
+ pemfile.read(), None
+ ),
+ mode="rb",
+ )
+ rsa_cert = load_vectors_from_file(
+ os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
+ loader=lambda pemfile: x509.load_pem_x509_certificate(
+ pemfile.read()
+ ),
+ mode="rb",
+ )
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA384())
+ .add_signer(rsa_cert, rsa_key, hashes.SHA512())
+ )
+ options = []
+ sig = builder.sign(serialization.Encoding.DER, options)
+ # There should be two SHA384 and two SHA512 OIDs in this structure
+ assert sig.count(b"\x06\t`\x86H\x01e\x03\x04\x02\x02") == 2
+ assert sig.count(b"\x06\t`\x86H\x01e\x03\x04\x02\x03") == 2
+ _pkcs7_verify(
+ serialization.Encoding.DER,
+ sig,
+ None,
+ [cert, rsa_cert],
+ options,
+ backend,
+ )
+
+ def test_add_additional_cert_not_a_cert(self, backend):
+ with pytest.raises(TypeError):
+ pkcs7.PKCS7SignatureBuilder().add_certificate(b"notacert")
+
+ def test_add_additional_cert(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ rsa_cert = load_vectors_from_file(
+ os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
+ loader=lambda pemfile: x509.load_pem_x509_certificate(
+ pemfile.read()
+ ),
+ mode="rb",
+ )
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA384())
+ .add_certificate(rsa_cert)
+ )
+ options = []
+ sig = builder.sign(serialization.Encoding.DER, options)
+ assert (
+ sig.count(rsa_cert.public_bytes(serialization.Encoding.DER)) == 1
+ )
+
+ def test_add_multiple_additional_certs(self, backend):
+ data = b"hello world"
+ cert, key = _load_cert_key()
+ rsa_cert = load_vectors_from_file(
+ os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
+ loader=lambda pemfile: x509.load_pem_x509_certificate(
+ pemfile.read()
+ ),
+ mode="rb",
+ )
+ builder = (
+ pkcs7.PKCS7SignatureBuilder()
+ .set_data(data)
+ .add_signer(cert, key, hashes.SHA384())
+ .add_certificate(rsa_cert)
+ .add_certificate(rsa_cert)
+ )
+ options = []
+ sig = builder.sign(serialization.Encoding.DER, options)
+ assert (
+ sig.count(rsa_cert.public_bytes(serialization.Encoding.DER)) == 2
+ )
diff --git a/tests/hazmat/primitives/test_poly1305.py b/tests/hazmat/primitives/test_poly1305.py
new file mode 100644
index 000000000..8779484ac
--- /dev/null
+++ b/tests/hazmat/primitives/test_poly1305.py
@@ -0,0 +1,156 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import os
+
+import pytest
+
+from cryptography.exceptions import (
+ AlreadyFinalized,
+ InvalidSignature,
+ _Reasons,
+)
+from cryptography.hazmat.primitives.poly1305 import Poly1305
+
+from ...utils import (
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
+)
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: not backend.poly1305_supported(),
+ skip_message="Requires OpenSSL without poly1305 support",
+)
+def test_poly1305_unsupported(backend):
+ with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MAC):
+ Poly1305(b"0" * 32)
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.poly1305_supported(),
+ skip_message="Requires OpenSSL with poly1305 support",
+)
+class TestPoly1305(object):
+ @pytest.mark.parametrize(
+ "vector",
+ load_vectors_from_file(
+ os.path.join("poly1305", "rfc7539.txt"), load_nist_vectors
+ ),
+ )
+ def test_vectors(self, vector, backend):
+ key = binascii.unhexlify(vector["key"])
+ msg = binascii.unhexlify(vector["msg"])
+ tag = binascii.unhexlify(vector["tag"])
+ poly = Poly1305(key)
+ poly.update(msg)
+ assert poly.finalize() == tag
+
+ assert Poly1305.generate_tag(key, msg) == tag
+ Poly1305.verify_tag(key, msg, tag)
+
+ def test_key_with_no_additional_references(self, backend):
+ poly = Poly1305(os.urandom(32))
+ assert len(poly.finalize()) == 16
+
+ def test_raises_after_finalize(self, backend):
+ poly = Poly1305(b"0" * 32)
+ poly.finalize()
+
+ with pytest.raises(AlreadyFinalized):
+ poly.update(b"foo")
+
+ with pytest.raises(AlreadyFinalized):
+ poly.finalize()
+
+ def test_reject_unicode(self, backend):
+ poly = Poly1305(b"0" * 32)
+ with pytest.raises(TypeError):
+ poly.update(u"")
+
+ with pytest.raises(TypeError):
+ Poly1305.generate_tag(b"0" * 32, u"")
+
+ def test_verify(self, backend):
+ poly = Poly1305(b"0" * 32)
+ poly.update(b"msg")
+ tag = poly.finalize()
+
+ with pytest.raises(AlreadyFinalized):
+ poly.verify(b"")
+
+ poly2 = Poly1305(b"0" * 32)
+ poly2.update(b"msg")
+ poly2.verify(tag)
+
+ Poly1305.verify_tag(b"0" * 32, b"msg", tag)
+
+ def test_invalid_verify(self, backend):
+ poly = Poly1305(b"0" * 32)
+ poly.update(b"msg")
+ with pytest.raises(InvalidSignature):
+ poly.verify(b"")
+
+ p2 = Poly1305(b"0" * 32)
+ p2.update(b"msg")
+ with pytest.raises(InvalidSignature):
+ p2.verify(b"\x00" * 16)
+
+ with pytest.raises(InvalidSignature):
+ Poly1305.verify_tag(b"0" * 32, b"msg", b"\x00" * 16)
+
+ def test_verify_reject_unicode(self, backend):
+ poly = Poly1305(b"0" * 32)
+ with pytest.raises(TypeError):
+ poly.verify(u"")
+
+ with pytest.raises(TypeError):
+ Poly1305.verify_tag(b"0" * 32, b"msg", u"")
+
+ def test_invalid_key_type(self, backend):
+ with pytest.raises(TypeError):
+ Poly1305(object())
+
+ with pytest.raises(TypeError):
+ Poly1305.generate_tag(object(), b"msg")
+
+ def test_invalid_key_length(self, backend):
+ with pytest.raises(ValueError):
+ Poly1305(b"0" * 31)
+
+ with pytest.raises(ValueError):
+ Poly1305.generate_tag(b"0" * 31, b"msg")
+
+ with pytest.raises(ValueError):
+ Poly1305(b"0" * 33)
+
+ with pytest.raises(ValueError):
+ Poly1305.generate_tag(b"0" * 33, b"msg")
+
+ def test_buffer_protocol(self, backend):
+ key = binascii.unhexlify(
+ b"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cb"
+ b"c207075c0"
+ )
+ msg = binascii.unhexlify(
+ b"2754776173206272696c6c69672c20616e642074686520736c69746"
+ b"87920746f7665730a446964206779726520616e642067696d626c65"
+ b"20696e2074686520776162653a0a416c6c206d696d7379207765726"
+ b"52074686520626f726f676f7665732c0a416e6420746865206d6f6d"
+ b"65207261746873206f757467726162652e"
+ )
+ key = bytearray(key)
+ poly = Poly1305(key)
+ poly.update(bytearray(msg))
+ assert poly.finalize() == binascii.unhexlify(
+ b"4541669a7eaaee61e708dc7cbcc5eb62"
+ )
+
+ assert Poly1305.generate_tag(key, msg) == binascii.unhexlify(
+ b"4541669a7eaaee61e708dc7cbcc5eb62"
+ )
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 65d88f547..61c481504 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -6,41 +6,67 @@ from __future__ import absolute_import, division, print_function
import binascii
import itertools
-import math
import os
import pytest
from cryptography.exceptions import (
- AlreadyFinalized, InvalidSignature, _Reasons
+ AlreadyFinalized,
+ InvalidSignature,
+ _Reasons,
)
from cryptography.hazmat.backends.interfaces import (
- PEMSerializationBackend, RSABackend
+ PEMSerializationBackend,
+ RSABackend,
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import (
- padding, rsa, utils as asym_utils
+ padding,
+ rsa,
+ utils as asym_utils,
)
from cryptography.hazmat.primitives.asymmetric.rsa import (
- RSAPrivateNumbers, RSAPublicNumbers
+ RSAPrivateNumbers,
+ RSAPublicNumbers,
)
from cryptography.utils import CryptographyDeprecationWarning
from .fixtures_rsa import (
- RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027, RSA_KEY_1028,
- RSA_KEY_1029, RSA_KEY_1030, RSA_KEY_1031, RSA_KEY_1536, RSA_KEY_2048,
- RSA_KEY_2048_ALT, RSA_KEY_512, RSA_KEY_512_ALT, RSA_KEY_522, RSA_KEY_599,
- RSA_KEY_745, RSA_KEY_768,
+ RSA_KEY_1024,
+ RSA_KEY_1025,
+ RSA_KEY_1026,
+ RSA_KEY_1027,
+ RSA_KEY_1028,
+ RSA_KEY_1029,
+ RSA_KEY_1030,
+ RSA_KEY_1031,
+ RSA_KEY_1536,
+ RSA_KEY_2048,
+ RSA_KEY_2048_ALT,
+ RSA_KEY_512,
+ RSA_KEY_512_ALT,
+ RSA_KEY_522,
+ RSA_KEY_599,
+ RSA_KEY_745,
+ RSA_KEY_768,
+ RSA_KEY_CORRUPTED,
)
from .utils import (
- _check_rsa_private_numbers, generate_rsa_verification_test
+ _check_rsa_private_numbers,
+ generate_rsa_verification_test,
+ skip_fips_traditional_openssl,
)
from ...doubles import (
- DummyAsymmetricPadding, DummyHashAlgorithm, DummyKeySerializationEncryption
+ DummyAsymmetricPadding,
+ DummyHashAlgorithm,
+ DummyKeySerializationEncryption,
)
from ...utils import (
- load_nist_vectors, load_pkcs1_vectors, load_rsa_nist_vectors,
- load_vectors_from_file, raises_unsupported_algorithm
+ load_nist_vectors,
+ load_pkcs1_vectors,
+ load_rsa_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
@@ -89,11 +115,9 @@ def _build_oaep_sha2_vectors():
load_vectors_from_file(
os.path.join(
base_path,
- "oaep-{0}-{1}.txt".format(
- mgf1alg.name, oaepalg.name
- )
+ "oaep-{}-{}.txt".format(mgf1alg.name, oaepalg.name),
),
- load_pkcs1_vectors
+ load_pkcs1_vectors,
)
)
# We've loaded the files, but the loaders don't give us any information
@@ -107,12 +131,11 @@ def _build_oaep_sha2_vectors():
def _skip_pss_hash_algorithm_unsupported(backend, hash_alg):
if not backend.rsa_padding_supported(
padding.PSS(
- mgf=padding.MGF1(hash_alg),
- salt_length=padding.PSS.MAX_LENGTH
+ mgf=padding.MGF1(hash_alg), salt_length=padding.PSS.MAX_LENGTH
)
):
pytest.skip(
- "Does not support {0} in MGF1 using PSS.".format(hash_alg.name)
+ "Does not support {} in MGF1 using PSS.".format(hash_alg.name)
)
@@ -127,19 +150,22 @@ def test_modular_inverse():
"d1f9f6c09fd3d38987f7970247b85a6da84907753d42ec52bc23b745093f4fff5cff3"
"617ce43d00121a9accc0051f519c76e08cf02fc18acfe4c9e6aea18da470a2b611d2e"
"56a7b35caa2c0239bc041a53cc5875ca0b668ae6377d4b23e932d8c995fd1e58ecfd8"
- "c4b73259c0d8a54d691cca3f6fb85c8a5c1baf588e898d481", 16
+ "c4b73259c0d8a54d691cca3f6fb85c8a5c1baf588e898d481",
+ 16,
)
q = int(
"d1519255eb8f678c86cfd06802d1fbef8b664441ac46b73d33d13a8404580a33a8e74"
"cb2ea2e2963125b3d454d7a922cef24dd13e55f989cbabf64255a736671f4629a47b5"
"b2347cfcd669133088d1c159518531025297c2d67c9da856a12e80222cd03b4c6ec0f"
- "86c957cb7bb8de7a127b645ec9e820aa94581e4762e209f01", 16
+ "86c957cb7bb8de7a127b645ec9e820aa94581e4762e209f01",
+ 16,
)
assert rsa._modinv(q, p) == int(
"0275e06afa722999315f8f322275483e15e2fb46d827b17800f99110b269a6732748f"
"624a382fa2ed1ec68c99f7fc56fb60e76eea51614881f497ba7034c17dde955f92f15"
"772f8b2b41f3e56d88b1e096cdd293eba4eae1e82db815e0fadea0c4ec971bc6fd875"
- "c20e67e48c31a611e98d32c6213ae4c4d7b53023b2f80c538", 16
+ "c20e67e48c31a611e98d32c6213ae4c4d7b53023b2f80c538",
+ 16,
)
@@ -148,11 +174,18 @@ class TestRSA(object):
@pytest.mark.parametrize(
("public_exponent", "key_size"),
itertools.product(
- (3, 5, 65537),
- (1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1536, 2048)
- )
+ (3, 65537),
+ (1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1536, 2048),
+ ),
)
def test_generate_rsa_keys(self, backend, public_exponent, key_size):
+ if backend._fips_enabled:
+ if key_size < backend._fips_rsa_min_key_size:
+ pytest.skip("Key size not FIPS compliant: {}".format(key_size))
+ if public_exponent < backend._fips_rsa_min_public_exponent:
+ pytest.skip(
+ "Exponent not FIPS compliant: {}".format(public_exponent)
+ )
skey = rsa.generate_private_key(public_exponent, key_size, backend)
assert skey.key_size == key_size
@@ -162,33 +195,39 @@ class TestRSA(object):
def test_generate_bad_public_exponent(self, backend):
with pytest.raises(ValueError):
- rsa.generate_private_key(public_exponent=1,
- key_size=2048,
- backend=backend)
+ rsa.generate_private_key(
+ public_exponent=1, key_size=2048, backend=backend
+ )
+
+ with pytest.raises(ValueError):
+ rsa.generate_private_key(
+ public_exponent=4, key_size=2048, backend=backend
+ )
with pytest.raises(ValueError):
- rsa.generate_private_key(public_exponent=4,
- key_size=2048,
- backend=backend)
+ rsa.generate_private_key(
+ public_exponent=65535, key_size=2048, backend=backend
+ )
def test_cant_generate_insecure_tiny_key(self, backend):
with pytest.raises(ValueError):
- rsa.generate_private_key(public_exponent=65537,
- key_size=511,
- backend=backend)
+ rsa.generate_private_key(
+ public_exponent=65537, key_size=511, backend=backend
+ )
with pytest.raises(ValueError):
- rsa.generate_private_key(public_exponent=65537,
- key_size=256,
- backend=backend)
+ rsa.generate_private_key(
+ public_exponent=65537, key_size=256, backend=backend
+ )
@pytest.mark.parametrize(
"pkcs1_example",
load_vectors_from_file(
os.path.join(
- "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"),
- load_pkcs1_vectors
- )
+ "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"
+ ),
+ load_pkcs1_vectors,
+ ),
)
def test_load_pss_vect_example_keys(self, pkcs1_example):
secret, public = pkcs1_example
@@ -201,15 +240,13 @@ class TestRSA(object):
dmq1=secret["dmq1"],
iqmp=secret["iqmp"],
public_numbers=rsa.RSAPublicNumbers(
- e=secret["public_exponent"],
- n=secret["modulus"]
- )
+ e=secret["public_exponent"], n=secret["modulus"]
+ ),
)
_check_rsa_private_numbers(private_num)
public_num = rsa.RSAPublicNumbers(
- e=public["public_exponent"],
- n=public["modulus"]
+ e=public["public_exponent"], n=public["modulus"]
)
assert public_num
@@ -223,17 +260,18 @@ class TestRSA(object):
"vector",
load_vectors_from_file(
os.path.join("asymmetric", "RSA", "oaep-label.txt"),
- load_nist_vectors)
+ load_nist_vectors,
+ ),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
- label=b"label"
+ label=b"label",
)
),
- skip_message="Does not support RSA OAEP labels"
+ skip_message="Does not support RSA OAEP labels",
)
def test_oaep_label_decrypt(self, vector, backend):
private_key = serialization.load_der_private_key(
@@ -245,8 +283,8 @@ class TestRSA(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA512()),
algorithm=hashes.SHA512(),
- label=binascii.unhexlify(vector["oaeplabel"])
- )
+ label=binascii.unhexlify(vector["oaeplabel"]),
+ ),
)
assert vector["output"][1:-1] == decrypted
@@ -255,17 +293,17 @@ class TestRSA(object):
[
(b"amazing encrypted msg", b"some label"),
(b"amazing encrypted msg", b""),
- ]
+ ],
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
- label=b"label"
+ label=b"label",
)
),
- skip_message="Does not support RSA OAEP labels"
+ skip_message="Does not support RSA OAEP labels",
)
def test_oaep_label_roundtrip(self, msg, label, backend):
private_key = RSA_KEY_2048.private_key(backend)
@@ -274,54 +312,52 @@ class TestRSA(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
- label=label
- )
+ label=label,
+ ),
)
pt = private_key.decrypt(
ct,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
- label=label
- )
+ label=label,
+ ),
)
assert pt == msg
@pytest.mark.parametrize(
("enclabel", "declabel"),
- [
- (b"label1", b"label2"),
- (b"label3", b""),
- (b"", b"label4"),
- ]
+ [(b"label1", b"label2"), (b"label3", b""), (b"", b"label4")],
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
- label=b"label"
+ label=b"label",
)
),
- skip_message="Does not support RSA OAEP labels"
+ skip_message="Does not support RSA OAEP labels",
)
def test_oaep_wrong_label(self, enclabel, declabel, backend):
private_key = RSA_KEY_2048.private_key(backend)
msg = b"test"
ct = private_key.public_key().encrypt(
- msg, padding.OAEP(
+ msg,
+ padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
- label=enclabel
- )
+ label=enclabel,
+ ),
)
with pytest.raises(ValueError):
private_key.decrypt(
- ct, padding.OAEP(
+ ct,
+ padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
- label=declabel
- )
+ label=declabel,
+ ),
)
@pytest.mark.supported(
@@ -329,10 +365,10 @@ class TestRSA(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
- label=b"label"
+ label=b"label",
)
),
- skip_message="Requires backend without RSA OAEP label support"
+ skip_message="Requires backend without RSA OAEP label support",
)
def test_unsupported_oaep_label_decrypt(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -342,8 +378,8 @@ class TestRSA(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=b"label"
- )
+ label=b"label",
+ ),
)
@@ -360,15 +396,16 @@ class TestRSASignature(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
@pytest.mark.parametrize(
"pkcs1_example",
- _flatten_pkcs1_examples(load_vectors_from_file(
- os.path.join(
- "asymmetric", "RSA", "pkcs1v15sign-vectors.txt"),
- load_pkcs1_vectors
- ))
+ _flatten_pkcs1_examples(
+ load_vectors_from_file(
+ os.path.join("asymmetric", "RSA", "pkcs1v15sign-vectors.txt"),
+ load_pkcs1_vectors,
+ )
+ ),
)
def test_pkcs1v15_signing(self, pkcs1_example, backend):
private, public, example = pkcs1_example
@@ -380,14 +417,13 @@ class TestRSASignature(object):
dmq1=private["dmq1"],
iqmp=private["iqmp"],
public_numbers=rsa.RSAPublicNumbers(
- e=private["public_exponent"],
- n=private["modulus"]
- )
+ e=private["public_exponent"], n=private["modulus"]
+ ),
).private_key(backend)
signature = private_key.sign(
binascii.unhexlify(example["message"]),
padding.PKCS1v15(),
- hashes.SHA1()
+ hashes.SHA1(),
)
assert binascii.hexlify(signature) == example["signature"]
@@ -395,18 +431,21 @@ class TestRSASignature(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
@pytest.mark.parametrize(
"pkcs1_example",
- _flatten_pkcs1_examples(load_vectors_from_file(
- os.path.join(
- "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"),
- load_pkcs1_vectors
- ))
+ _flatten_pkcs1_examples(
+ load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"
+ ),
+ load_pkcs1_vectors,
+ )
+ ),
)
def test_pss_signing(self, pkcs1_example, backend):
private, public, example = pkcs1_example
@@ -418,23 +457,21 @@ class TestRSASignature(object):
dmq1=private["dmq1"],
iqmp=private["iqmp"],
public_numbers=rsa.RSAPublicNumbers(
- e=private["public_exponent"],
- n=private["modulus"]
- )
+ e=private["public_exponent"], n=private["modulus"]
+ ),
).private_key(backend)
public_key = rsa.RSAPublicNumbers(
- e=public["public_exponent"],
- n=public["modulus"]
+ e=public["public_exponent"], n=public["modulus"]
).public_key(backend)
signature = private_key.sign(
binascii.unhexlify(example["message"]),
padding.PSS(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
),
- hashes.SHA1()
+ hashes.SHA1(),
)
- assert len(signature) == math.ceil(private_key.key_size / 8.0)
+ assert len(signature) == (private_key.key_size + 7) // 8
# PSS signatures contain randomness so we can't do an exact
# signature check. Instead we'll verify that the signature created
# successfully verifies.
@@ -443,22 +480,21 @@ class TestRSASignature(object):
binascii.unhexlify(example["message"]),
padding.PSS(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
),
hashes.SHA1(),
)
@pytest.mark.parametrize(
"hash_alg",
- [hashes.SHA224(), hashes.SHA256(), hashes.SHA384(), hashes.SHA512()]
+ [hashes.SHA224(), hashes.SHA256(), hashes.SHA384(), hashes.SHA512()],
)
def test_pss_signing_sha2(self, hash_alg, backend):
_skip_pss_hash_algorithm_unsupported(backend, hash_alg)
private_key = RSA_KEY_768.private_key(backend)
public_key = private_key.public_key()
pss = padding.PSS(
- mgf=padding.MGF1(hash_alg),
- salt_length=padding.PSS.MAX_LENGTH
+ mgf=padding.MGF1(hash_alg), salt_length=padding.PSS.MAX_LENGTH
)
msg = b"testing signature"
signature = private_key.sign(msg, pss, hash_alg)
@@ -466,15 +502,15 @@ class TestRSASignature(object):
@pytest.mark.supported(
only_if=lambda backend: (
- backend.hash_supported(hashes.SHA512()) and
- backend.rsa_padding_supported(
+ backend.hash_supported(hashes.SHA512())
+ and backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
)
),
- skip_message="Does not support SHA512."
+ skip_message="Does not support SHA512.",
)
def test_pss_minimum_key_size_for_digest(self, backend):
private_key = RSA_KEY_522.private_key(backend)
@@ -482,23 +518,23 @@ class TestRSASignature(object):
b"no failure",
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
),
- hashes.SHA512()
+ hashes.SHA512(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
@pytest.mark.supported(
only_if=lambda backend: backend.hash_supported(hashes.SHA512()),
- skip_message="Does not support SHA512."
+ skip_message="Does not support SHA512.",
)
def test_pss_signing_digest_too_large_for_key_size(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -507,19 +543,19 @@ class TestRSASignature(object):
b"msg",
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
),
- hashes.SHA512()
+ hashes.SHA512(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_pss_signing_salt_length_too_long(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -527,17 +563,16 @@ class TestRSASignature(object):
private_key.sign(
b"failure coming",
padding.PSS(
- mgf=padding.MGF1(hashes.SHA1()),
- salt_length=1000000
+ mgf=padding.MGF1(hashes.SHA1()), salt_length=1000000
),
- hashes.SHA1()
+ hashes.SHA1(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_use_after_finalize(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -564,7 +599,7 @@ class TestRSASignature(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_unsupported_pss_mgf(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -572,40 +607,33 @@ class TestRSASignature(object):
private_key.sign(
b"msg",
padding.PSS(
- mgf=DummyMGF(),
- salt_length=padding.PSS.MAX_LENGTH
+ mgf=DummyMGF(), salt_length=padding.PSS.MAX_LENGTH
),
- hashes.SHA1()
+ hashes.SHA1(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_pkcs1_digest_too_large_for_key_size(self, backend):
private_key = RSA_KEY_599.private_key(backend)
with pytest.raises(ValueError):
private_key.sign(
- b"failure coming",
- padding.PKCS1v15(),
- hashes.SHA512()
+ b"failure coming", padding.PKCS1v15(), hashes.SHA512()
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_pkcs1_minimum_key_size(self, backend):
private_key = RSA_KEY_745.private_key(backend)
- private_key.sign(
- b"no failure",
- padding.PKCS1v15(),
- hashes.SHA512()
- )
+ private_key.sign(b"no failure", padding.PKCS1v15(), hashes.SHA512())
def test_sign(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -620,7 +648,7 @@ class TestRSASignature(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_prehashed_sign(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -636,14 +664,15 @@ class TestRSASignature(object):
@pytest.mark.supported(
only_if=lambda backend: backend.hash_supported(
- hashes.BLAKE2s(digest_size=32)),
+ hashes.BLAKE2s(digest_size=32)
+ ),
skip_message="Does not support BLAKE2s",
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_unsupported_hash(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -656,7 +685,7 @@ class TestRSASignature(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_prehashed_digest_mismatch(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -673,31 +702,50 @@ class TestRSASignature(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_prehashed_unsupported_in_signer_ctx(self, backend):
private_key = RSA_KEY_512.private_key(backend)
- with pytest.raises(TypeError), \
- pytest.warns(CryptographyDeprecationWarning):
+ with pytest.raises(TypeError), pytest.warns(
+ CryptographyDeprecationWarning
+ ):
private_key.signer(
- padding.PKCS1v15(),
- asym_utils.Prehashed(hashes.SHA1())
+ padding.PKCS1v15(), asym_utils.Prehashed(hashes.SHA1())
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_prehashed_unsupported_in_verifier_ctx(self, backend):
public_key = RSA_KEY_512.private_key(backend).public_key()
- with pytest.raises(TypeError), \
- pytest.warns(CryptographyDeprecationWarning):
+ with pytest.raises(TypeError), pytest.warns(
+ CryptographyDeprecationWarning
+ ):
public_key.verifier(
b"0" * 64,
padding.PKCS1v15(),
- asym_utils.Prehashed(hashes.SHA1())
+ asym_utils.Prehashed(hashes.SHA1()),
+ )
+
+ def test_prehashed_unsupported_in_signature_recover(self, backend):
+ private_key = RSA_KEY_512.private_key(backend)
+ public_key = private_key.public_key()
+ signature = private_key.sign(
+ b"sign me", padding.PKCS1v15(), hashes.SHA1()
+ )
+ prehashed_alg = asym_utils.Prehashed(hashes.SHA1())
+ with pytest.raises(TypeError):
+ public_key.recover_data_from_signature(
+ signature, padding.PKCS1v15(), prehashed_alg
+ )
+
+ def test_corrupted_private_key(self, backend):
+ with pytest.raises(ValueError):
+ serialization.load_pem_private_key(
+ RSA_KEY_CORRUPTED, password=None, backend=backend
)
@@ -707,34 +755,49 @@ class TestRSAVerification(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
@pytest.mark.parametrize(
"pkcs1_example",
- _flatten_pkcs1_examples(load_vectors_from_file(
- os.path.join(
- "asymmetric", "RSA", "pkcs1v15sign-vectors.txt"),
- load_pkcs1_vectors
- ))
+ _flatten_pkcs1_examples(
+ load_vectors_from_file(
+ os.path.join("asymmetric", "RSA", "pkcs1v15sign-vectors.txt"),
+ load_pkcs1_vectors,
+ )
+ ),
)
def test_pkcs1v15_verification(self, pkcs1_example, backend):
private, public, example = pkcs1_example
public_key = rsa.RSAPublicNumbers(
- e=public["public_exponent"],
- n=public["modulus"]
+ e=public["public_exponent"], n=public["modulus"]
).public_key(backend)
+ signature = binascii.unhexlify(example["signature"])
+ message = binascii.unhexlify(example["message"])
public_key.verify(
- binascii.unhexlify(example["signature"]),
- binascii.unhexlify(example["message"]),
- padding.PKCS1v15(),
- hashes.SHA1()
+ signature, message, padding.PKCS1v15(), hashes.SHA1()
+ )
+
+ # Test digest recovery by providing hash
+ digest = hashes.Hash(hashes.SHA1())
+ digest.update(message)
+ msg_digest = digest.finalize()
+ rec_msg_digest = public_key.recover_data_from_signature(
+ signature, padding.PKCS1v15(), hashes.SHA1()
)
+ assert msg_digest == rec_msg_digest
+
+ # Test recovery of all data (full DigestInfo) with hash alg. as None
+ rec_sig_data = public_key.recover_data_from_signature(
+ signature, padding.PKCS1v15(), None
+ )
+ assert len(rec_sig_data) > len(msg_digest)
+ assert msg_digest == rec_sig_data[-len(msg_digest) :]
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_invalid_pkcs1v15_signature_wrong_data(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -744,10 +807,18 @@ class TestRSAVerification(object):
)
with pytest.raises(InvalidSignature):
public_key.verify(
- signature,
- b"incorrect data",
- padding.PKCS1v15(),
- hashes.SHA1()
+ signature, b"incorrect data", padding.PKCS1v15(), hashes.SHA1()
+ )
+
+ def test_invalid_pkcs1v15_signature_recover_wrong_hash_alg(self, backend):
+ private_key = RSA_KEY_512.private_key(backend)
+ public_key = private_key.public_key()
+ signature = private_key.sign(
+ b"sign me", padding.PKCS1v15(), hashes.SHA1()
+ )
+ with pytest.raises(InvalidSignature):
+ public_key.recover_data_from_signature(
+ signature, padding.PKCS1v15(), hashes.SHA256()
)
def test_invalid_signature_sequence_removed(self, backend):
@@ -782,14 +853,14 @@ class TestRSAVerification(object):
sig,
binascii.unhexlify(b"313233343030"),
padding.PKCS1v15(),
- hashes.SHA256()
+ hashes.SHA256(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_invalid_pkcs1v15_signature_wrong_key(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -804,54 +875,53 @@ class TestRSAVerification(object):
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
- padding.PSS(
- mgf=padding.MGF1(hashes.SHA1()),
- salt_length=20
- )
+ padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=20)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
@pytest.mark.parametrize(
"pkcs1_example",
- _flatten_pkcs1_examples(load_vectors_from_file(
- os.path.join(
- "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"),
- load_pkcs1_vectors
- ))
+ _flatten_pkcs1_examples(
+ load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"
+ ),
+ load_pkcs1_vectors,
+ )
+ ),
)
def test_pss_verification(self, pkcs1_example, backend):
private, public, example = pkcs1_example
public_key = rsa.RSAPublicNumbers(
- e=public["public_exponent"],
- n=public["modulus"]
+ e=public["public_exponent"], n=public["modulus"]
).public_key(backend)
public_key.verify(
binascii.unhexlify(example["signature"]),
binascii.unhexlify(example["message"]),
padding.PSS(
- mgf=padding.MGF1(algorithm=hashes.SHA1()),
- salt_length=20
+ mgf=padding.MGF1(algorithm=hashes.SHA1()), salt_length=20
),
- hashes.SHA1()
+ hashes.SHA1(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_invalid_pss_signature_wrong_data(self, backend):
public_key = rsa.RSAPublicNumbers(
n=int(
b"dffc2137d5e810cde9e4b4612f5796447218bab913b3fa98bdf7982e4fa6"
b"ec4d6653ef2b29fb1642b095befcbea6decc178fb4bed243d3c3592c6854"
- b"6af2d3f3", 16
+ b"6af2d3f3",
+ 16,
),
- e=65537
+ e=65537,
).public_key(backend)
signature = binascii.unhexlify(
b"0e68c3649df91c5bc3665f96e157efa75b71934aaa514d91e94ca8418d100f45"
@@ -863,19 +933,19 @@ class TestRSAVerification(object):
b"incorrect data",
padding.PSS(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
),
- hashes.SHA1()
+ hashes.SHA1(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_invalid_pss_signature_wrong_key(self, backend):
signature = binascii.unhexlify(
@@ -888,9 +958,10 @@ class TestRSAVerification(object):
b"5a95441be90866a14c4d2e139cd16db540ec6c7abab13ffff91443fd46a8"
b"960cbb7658ded26a5c95c86f6e40384e1c1239c63e541ba221191c4dd303"
b"231b42e33c6dbddf5ec9a746f09bf0c25d0f8d27f93ee0ae5c0d723348f4"
- b"030d3581e13522e1", 16
+ b"030d3581e13522e1",
+ 16,
),
- e=65537
+ e=65537,
).public_key(backend)
with pytest.raises(InvalidSignature):
public_key.verify(
@@ -898,51 +969,71 @@ class TestRSAVerification(object):
b"sign me",
padding.PSS(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
),
- hashes.SHA1()
+ hashes.SHA1(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_invalid_pss_signature_data_too_large_for_modulus(self, backend):
+ # 2048 bit PSS signature
signature = binascii.unhexlify(
- b"cb43bde4f7ab89eb4a79c6e8dd67e0d1af60715da64429d90c716a490b799c29"
- b"194cf8046509c6ed851052367a74e2e92d9b38947ed74332acb115a03fcc0222"
- )
- public_key = rsa.RSAPublicNumbers(
- n=int(
- b"381201f4905d67dfeb3dec131a0fbea773489227ec7a1448c3109189ac68"
- b"5a95441be90866a14c4d2e139cd16db540ec6c7abab13ffff91443fd46a8"
- b"960cbb7658ded26a5c95c86f6e40384e1c1239c63e541ba221191c4dd303"
- b"231b42e33c6dbddf5ec9a746f09bf0c25d0f8d27f93ee0ae5c0d723348f4"
- b"030d3581e13522", 16
- ),
- e=65537
- ).public_key(backend)
+ b"58750fc3d2f560d1f3e37c8e28bc8da6d3e93f5d58f8becd25b1c931eea30fea"
+ b"54cb17d44b90104a0aacb7fe9ffa2a59c5788435911d63de78178d21eb875ccd"
+ b"0b07121b641ed4fe6bcb1ca5060322765507b4f24bdba8a698a8e4e07e6bf2c4"
+ b"7a736abe5a912e85cd32f648f3e043b4385e8b612dcce342c5fddf18c524deb5"
+ b"6295b95f6dfa759b2896b793628a90f133e74c1ff7d3af43e3f7ee792df2e5b6"
+ b"a19e996ac3676884354899a437b3ae4e3ac91976c336c332a3b1db0d172b19cb"
+ b"40ad3d871296cfffb3c889ce74a179a3e290852c35d59525afe4b39dc907fad2"
+ b"ac462c50a488dca486031a3dc8c4cdbbc53e9f71d64732e1533a5d1249b833ce"
+ )
+ # 1024 bit key
+ public_key = RSA_KEY_1024.private_key(backend).public_key()
with pytest.raises(InvalidSignature):
public_key.verify(
signature,
b"sign me",
padding.PSS(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
),
- hashes.SHA1()
+ hashes.SHA1(),
+ )
+
+ def test_invalid_pss_signature_recover(self, backend):
+ private_key = RSA_KEY_1024.private_key(backend)
+ public_key = private_key.public_key()
+ pss_padding = padding.PSS(
+ mgf=padding.MGF1(algorithm=hashes.SHA1()),
+ salt_length=padding.PSS.MAX_LENGTH,
+ )
+ signature = private_key.sign(b"sign me", pss_padding, hashes.SHA1())
+
+ # Hash algorithm can not be absent for PSS padding
+ with pytest.raises(TypeError):
+ public_key.recover_data_from_signature(
+ signature, pss_padding, None
+ )
+
+ # Signature data recovery not supported with PSS
+ with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
+ public_key.recover_data_from_signature(
+ signature, pss_padding, hashes.SHA1()
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_use_after_finalize(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -953,9 +1044,7 @@ class TestRSAVerification(object):
with pytest.warns(CryptographyDeprecationWarning):
verifier = public_key.verifier(
- signature,
- padding.PKCS1v15(),
- hashes.SHA1()
+ signature, padding.PKCS1v15(), hashes.SHA1()
)
verifier.update(b"sign me")
verifier.verify()
@@ -976,19 +1065,16 @@ class TestRSAVerification(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_signature_not_bytes(self, backend):
public_key = RSA_KEY_512.public_numbers.public_key(backend)
signature = 1234
- with pytest.raises(TypeError), \
- pytest.warns(CryptographyDeprecationWarning):
- public_key.verifier(
- signature,
- padding.PKCS1v15(),
- hashes.SHA1()
- )
+ with pytest.raises(TypeError), pytest.warns(
+ CryptographyDeprecationWarning
+ ):
+ public_key.verifier(signature, padding.PKCS1v15(), hashes.SHA1())
def test_padding_incorrect_type(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -1000,7 +1086,7 @@ class TestRSAVerification(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_unsupported_pss_mgf(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -1010,24 +1096,23 @@ class TestRSAVerification(object):
b"sig",
b"msg",
padding.PSS(
- mgf=DummyMGF(),
- salt_length=padding.PSS.MAX_LENGTH
+ mgf=DummyMGF(), salt_length=padding.PSS.MAX_LENGTH
),
- hashes.SHA1()
+ hashes.SHA1(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
@pytest.mark.supported(
only_if=lambda backend: backend.hash_supported(hashes.SHA512()),
- skip_message="Does not support SHA512."
+ skip_message="Does not support SHA512.",
)
def test_pss_verify_digest_too_large_for_key_size(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -1042,19 +1127,19 @@ class TestRSAVerification(object):
b"msg doesn't matter",
padding.PSS(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
),
- hashes.SHA512()
+ hashes.SHA512(),
)
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS."
+ skip_message="Does not support PSS.",
)
def test_pss_verify_salt_length_too_long(self, backend):
signature = binascii.unhexlify(
@@ -1065,9 +1150,10 @@ class TestRSAVerification(object):
n=int(
b"d309e4612809437548b747d7f9eb9cd3340f54fe42bb3f84a36933b0839c"
b"11b0c8b7f67e11f7252370161e31159c49c784d4bc41c42a78ce0f0b40a3"
- b"ca8ffb91", 16
+ b"ca8ffb91",
+ 16,
),
- e=65537
+ e=65537,
).public_key(backend)
with pytest.raises(InvalidSignature):
public_key.verify(
@@ -1077,9 +1163,9 @@ class TestRSAVerification(object):
mgf=padding.MGF1(
algorithm=hashes.SHA1(),
),
- salt_length=1000000
+ salt_length=1000000,
),
- hashes.SHA1()
+ hashes.SHA1(),
)
def test_verify(self, backend):
@@ -1121,219 +1207,239 @@ class TestRSAPSSMGF1Verification(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA1()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS using MGF1 with SHA1."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGenPSS_186-2.rsp",
- "SigGenPSS_186-3.rsp",
- "SigVerPSS_186-3.rsp",
- ],
- hashes.SHA1(),
- lambda params, hash_alg: padding.PSS(
- mgf=padding.MGF1(
- algorithm=hash_alg,
+ skip_message="Does not support PSS using MGF1 with SHA1.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGenPSS_186-2.rsp",
+ "SigGenPSS_186-3.rsp",
+ "SigVerPSS_186-3.rsp",
+ ],
+ hashes.SHA1(),
+ lambda params, hash_alg: padding.PSS(
+ mgf=padding.MGF1(
+ algorithm=hash_alg,
+ ),
+ salt_length=params["salt_length"],
),
- salt_length=params["salt_length"]
)
- ))
+ )
test_rsa_pss_mgf1_sha224 = pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA224()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS using MGF1 with SHA224."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGenPSS_186-2.rsp",
- "SigGenPSS_186-3.rsp",
- "SigVerPSS_186-3.rsp",
- ],
- hashes.SHA224(),
- lambda params, hash_alg: padding.PSS(
- mgf=padding.MGF1(
- algorithm=hash_alg,
+ skip_message="Does not support PSS using MGF1 with SHA224.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGenPSS_186-2.rsp",
+ "SigGenPSS_186-3.rsp",
+ "SigVerPSS_186-3.rsp",
+ ],
+ hashes.SHA224(),
+ lambda params, hash_alg: padding.PSS(
+ mgf=padding.MGF1(
+ algorithm=hash_alg,
+ ),
+ salt_length=params["salt_length"],
),
- salt_length=params["salt_length"]
)
- ))
+ )
test_rsa_pss_mgf1_sha256 = pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS using MGF1 with SHA256."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGenPSS_186-2.rsp",
- "SigGenPSS_186-3.rsp",
- "SigVerPSS_186-3.rsp",
- ],
- hashes.SHA256(),
- lambda params, hash_alg: padding.PSS(
- mgf=padding.MGF1(
- algorithm=hash_alg,
+ skip_message="Does not support PSS using MGF1 with SHA256.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGenPSS_186-2.rsp",
+ "SigGenPSS_186-3.rsp",
+ "SigVerPSS_186-3.rsp",
+ ],
+ hashes.SHA256(),
+ lambda params, hash_alg: padding.PSS(
+ mgf=padding.MGF1(
+ algorithm=hash_alg,
+ ),
+ salt_length=params["salt_length"],
),
- salt_length=params["salt_length"]
)
- ))
+ )
test_rsa_pss_mgf1_sha384 = pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA384()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS using MGF1 with SHA384."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGenPSS_186-2.rsp",
- "SigGenPSS_186-3.rsp",
- "SigVerPSS_186-3.rsp",
- ],
- hashes.SHA384(),
- lambda params, hash_alg: padding.PSS(
- mgf=padding.MGF1(
- algorithm=hash_alg,
+ skip_message="Does not support PSS using MGF1 with SHA384.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGenPSS_186-2.rsp",
+ "SigGenPSS_186-3.rsp",
+ "SigVerPSS_186-3.rsp",
+ ],
+ hashes.SHA384(),
+ lambda params, hash_alg: padding.PSS(
+ mgf=padding.MGF1(
+ algorithm=hash_alg,
+ ),
+ salt_length=params["salt_length"],
),
- salt_length=params["salt_length"]
)
- ))
+ )
test_rsa_pss_mgf1_sha512 = pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PSS(
mgf=padding.MGF1(hashes.SHA512()),
- salt_length=padding.PSS.MAX_LENGTH
+ salt_length=padding.PSS.MAX_LENGTH,
)
),
- skip_message="Does not support PSS using MGF1 with SHA512."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGenPSS_186-2.rsp",
- "SigGenPSS_186-3.rsp",
- "SigVerPSS_186-3.rsp",
- ],
- hashes.SHA512(),
- lambda params, hash_alg: padding.PSS(
- mgf=padding.MGF1(
- algorithm=hash_alg,
+ skip_message="Does not support PSS using MGF1 with SHA512.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGenPSS_186-2.rsp",
+ "SigGenPSS_186-3.rsp",
+ "SigVerPSS_186-3.rsp",
+ ],
+ hashes.SHA512(),
+ lambda params, hash_alg: padding.PSS(
+ mgf=padding.MGF1(
+ algorithm=hash_alg,
+ ),
+ salt_length=params["salt_length"],
),
- salt_length=params["salt_length"]
)
- ))
+ )
@pytest.mark.requires_backend_interface(interface=RSABackend)
class TestRSAPKCS1Verification(object):
test_rsa_pkcs1v15_verify_sha1 = pytest.mark.supported(
only_if=lambda backend: (
- backend.hash_supported(hashes.SHA1()) and
- backend.rsa_padding_supported(padding.PKCS1v15())
+ backend.hash_supported(hashes.SHA1())
+ and backend.rsa_padding_supported(padding.PKCS1v15())
),
- skip_message="Does not support SHA1 and PKCS1v1.5."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGen15_186-2.rsp",
- "SigGen15_186-3.rsp",
- "SigVer15_186-3.rsp",
- ],
- hashes.SHA1(),
- lambda params, hash_alg: padding.PKCS1v15()
- ))
+ skip_message="Does not support SHA1 and PKCS1v1.5.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGen15_186-2.rsp",
+ "SigGen15_186-3.rsp",
+ "SigVer15_186-3.rsp",
+ ],
+ hashes.SHA1(),
+ lambda params, hash_alg: padding.PKCS1v15(),
+ )
+ )
test_rsa_pkcs1v15_verify_sha224 = pytest.mark.supported(
only_if=lambda backend: (
- backend.hash_supported(hashes.SHA224()) and
- backend.rsa_padding_supported(padding.PKCS1v15())
+ backend.hash_supported(hashes.SHA224())
+ and backend.rsa_padding_supported(padding.PKCS1v15())
),
- skip_message="Does not support SHA224 and PKCS1v1.5."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGen15_186-2.rsp",
- "SigGen15_186-3.rsp",
- "SigVer15_186-3.rsp",
- ],
- hashes.SHA224(),
- lambda params, hash_alg: padding.PKCS1v15()
- ))
+ skip_message="Does not support SHA224 and PKCS1v1.5.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGen15_186-2.rsp",
+ "SigGen15_186-3.rsp",
+ "SigVer15_186-3.rsp",
+ ],
+ hashes.SHA224(),
+ lambda params, hash_alg: padding.PKCS1v15(),
+ )
+ )
test_rsa_pkcs1v15_verify_sha256 = pytest.mark.supported(
only_if=lambda backend: (
- backend.hash_supported(hashes.SHA256()) and
- backend.rsa_padding_supported(padding.PKCS1v15())
+ backend.hash_supported(hashes.SHA256())
+ and backend.rsa_padding_supported(padding.PKCS1v15())
),
- skip_message="Does not support SHA256 and PKCS1v1.5."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGen15_186-2.rsp",
- "SigGen15_186-3.rsp",
- "SigVer15_186-3.rsp",
- ],
- hashes.SHA256(),
- lambda params, hash_alg: padding.PKCS1v15()
- ))
+ skip_message="Does not support SHA256 and PKCS1v1.5.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGen15_186-2.rsp",
+ "SigGen15_186-3.rsp",
+ "SigVer15_186-3.rsp",
+ ],
+ hashes.SHA256(),
+ lambda params, hash_alg: padding.PKCS1v15(),
+ )
+ )
test_rsa_pkcs1v15_verify_sha384 = pytest.mark.supported(
only_if=lambda backend: (
- backend.hash_supported(hashes.SHA384()) and
- backend.rsa_padding_supported(padding.PKCS1v15())
+ backend.hash_supported(hashes.SHA384())
+ and backend.rsa_padding_supported(padding.PKCS1v15())
),
- skip_message="Does not support SHA384 and PKCS1v1.5."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGen15_186-2.rsp",
- "SigGen15_186-3.rsp",
- "SigVer15_186-3.rsp",
- ],
- hashes.SHA384(),
- lambda params, hash_alg: padding.PKCS1v15()
- ))
+ skip_message="Does not support SHA384 and PKCS1v1.5.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGen15_186-2.rsp",
+ "SigGen15_186-3.rsp",
+ "SigVer15_186-3.rsp",
+ ],
+ hashes.SHA384(),
+ lambda params, hash_alg: padding.PKCS1v15(),
+ )
+ )
test_rsa_pkcs1v15_verify_sha512 = pytest.mark.supported(
only_if=lambda backend: (
- backend.hash_supported(hashes.SHA512()) and
- backend.rsa_padding_supported(padding.PKCS1v15())
+ backend.hash_supported(hashes.SHA512())
+ and backend.rsa_padding_supported(padding.PKCS1v15())
),
- skip_message="Does not support SHA512 and PKCS1v1.5."
- )(generate_rsa_verification_test(
- load_rsa_nist_vectors,
- os.path.join("asymmetric", "RSA", "FIPS_186-2"),
- [
- "SigGen15_186-2.rsp",
- "SigGen15_186-3.rsp",
- "SigVer15_186-3.rsp",
- ],
- hashes.SHA512(),
- lambda params, hash_alg: padding.PKCS1v15()
- ))
+ skip_message="Does not support SHA512 and PKCS1v1.5.",
+ )(
+ generate_rsa_verification_test(
+ load_rsa_nist_vectors,
+ os.path.join("asymmetric", "RSA", "FIPS_186-2"),
+ [
+ "SigGen15_186-2.rsp",
+ "SigGen15_186-3.rsp",
+ "SigVer15_186-3.rsp",
+ ],
+ hashes.SHA512(),
+ lambda params, hash_alg: padding.PKCS1v15(),
+ )
+ )
class TestPSS(object):
@@ -1344,20 +1450,12 @@ class TestPSS(object):
def test_invalid_salt_length_not_integer(self):
with pytest.raises(TypeError):
padding.PSS(
- mgf=padding.MGF1(
- hashes.SHA1()
- ),
- salt_length=b"not_a_length"
+ mgf=padding.MGF1(hashes.SHA1()), salt_length=b"not_a_length"
)
def test_invalid_salt_length_negative_integer(self):
with pytest.raises(ValueError):
- padding.PSS(
- mgf=padding.MGF1(
- hashes.SHA1()
- ),
- salt_length=-1
- )
+ padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=-1)
def test_valid_pss_parameters(self):
algorithm = hashes.SHA1()
@@ -1390,11 +1488,7 @@ class TestOAEP(object):
def test_invalid_algorithm(self):
mgf = padding.MGF1(hashes.SHA1())
with pytest.raises(TypeError):
- padding.OAEP(
- mgf=mgf,
- algorithm=b"",
- label=None
- )
+ padding.OAEP(mgf=mgf, algorithm=b"", label=None)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -1403,15 +1497,16 @@ class TestRSADecryption(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
@pytest.mark.parametrize(
"vector",
- _flatten_pkcs1_examples(load_vectors_from_file(
- os.path.join(
- "asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"),
- load_pkcs1_vectors
- ))
+ _flatten_pkcs1_examples(
+ load_vectors_from_file(
+ os.path.join("asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"),
+ load_pkcs1_vectors,
+ )
+ ),
)
def test_decrypt_pkcs1v15_vectors(self, vector, backend):
private, public, example = vector
@@ -1423,12 +1518,11 @@ class TestRSADecryption(object):
dmq1=private["dmq1"],
iqmp=private["iqmp"],
public_numbers=rsa.RSAPublicNumbers(
- e=private["public_exponent"],
- n=private["modulus"]
- )
+ e=private["public_exponent"], n=private["modulus"]
+ ),
).private_key(backend)
ciphertext = binascii.unhexlify(example["encryption"])
- assert len(ciphertext) == math.ceil(skey.key_size / 8.0)
+ assert len(ciphertext) == (skey.key_size + 7) // 8
message = skey.decrypt(ciphertext, padding.PKCS1v15())
assert message == binascii.unhexlify(example["message"])
@@ -1441,35 +1535,29 @@ class TestRSADecryption(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_decrypt_invalid_decrypt(self, backend):
private_key = RSA_KEY_512.private_key(backend)
with pytest.raises(ValueError):
- private_key.decrypt(
- b"\x00" * 64,
- padding.PKCS1v15()
- )
+ private_key.decrypt(b"\x00" * 64, padding.PKCS1v15())
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_decrypt_ciphertext_too_large(self, backend):
private_key = RSA_KEY_512.private_key(backend)
with pytest.raises(ValueError):
- private_key.decrypt(
- b"\x00" * 65,
- padding.PKCS1v15()
- )
+ private_key.decrypt(b"\x00" * 65, padding.PKCS1v15())
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
def test_decrypt_ciphertext_too_small(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -1478,28 +1566,28 @@ class TestRSADecryption(object):
b"69d210f2b9bdfb48b12f9ea05009c77da257cc600ccefe3a6283789d8ea0"
)
with pytest.raises(ValueError):
- private_key.decrypt(
- ct,
- padding.PKCS1v15()
- )
+ private_key.decrypt(ct, padding.PKCS1v15())
@pytest.mark.supported(
only_if=lambda backend: backend.rsa_padding_supported(
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
+ label=None,
)
),
- skip_message="Does not support OAEP."
+ skip_message="Does not support OAEP.",
)
@pytest.mark.parametrize(
"vector",
- _flatten_pkcs1_examples(load_vectors_from_file(
- os.path.join(
- "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "oaep-vect.txt"),
- load_pkcs1_vectors
- ))
+ _flatten_pkcs1_examples(
+ load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "oaep-vect.txt"
+ ),
+ load_pkcs1_vectors,
+ )
+ ),
)
def test_decrypt_oaep_vectors(self, vector, backend):
private, public, example = vector
@@ -1511,17 +1599,16 @@ class TestRSADecryption(object):
dmq1=private["dmq1"],
iqmp=private["iqmp"],
public_numbers=rsa.RSAPublicNumbers(
- e=private["public_exponent"],
- n=private["modulus"]
- )
+ e=private["public_exponent"], n=private["modulus"]
+ ),
).private_key(backend)
message = skey.decrypt(
binascii.unhexlify(example["encryption"]),
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
- )
+ label=None,
+ ),
)
assert message == binascii.unhexlify(example["message"])
@@ -1530,15 +1617,14 @@ class TestRSADecryption(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA224()),
algorithm=hashes.SHA224(),
- label=None
+ label=None,
)
),
- skip_message="Does not support OAEP using SHA224 MGF1 and SHA224 hash."
- )
- @pytest.mark.parametrize(
- "vector",
- _build_oaep_sha2_vectors()
+ skip_message=(
+ "Does not support OAEP using SHA224 MGF1 and SHA224 hash."
+ ),
)
+ @pytest.mark.parametrize("vector", _build_oaep_sha2_vectors())
def test_decrypt_oaep_sha2_vectors(self, vector, backend):
private, public, example, mgf1_alg, hash_alg = vector
skey = rsa.RSAPrivateNumbers(
@@ -1549,17 +1635,16 @@ class TestRSADecryption(object):
dmq1=private["dmq1"],
iqmp=private["iqmp"],
public_numbers=rsa.RSAPublicNumbers(
- e=private["public_exponent"],
- n=private["modulus"]
- )
+ e=private["public_exponent"], n=private["modulus"]
+ ),
).private_key(backend)
message = skey.decrypt(
binascii.unhexlify(example["encryption"]),
padding.OAEP(
mgf=padding.MGF1(algorithm=mgf1_alg),
algorithm=hash_alg,
- label=None
- )
+ label=None,
+ ),
)
assert message == binascii.unhexlify(example["message"])
@@ -1568,24 +1653,24 @@ class TestRSADecryption(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
+ label=None,
)
),
- skip_message="Does not support OAEP."
+ skip_message="Does not support OAEP.",
)
def test_invalid_oaep_decryption(self, backend):
- # More recent versions of OpenSSL may raise RSA_R_OAEP_DECODING_ERROR
- # This test triggers it and confirms that we properly handle it. Other
- # backends should also return the proper ValueError.
+ # More recent versions of OpenSSL may raise different errors.
+ # This test triggers a failure and confirms that we properly handle
+ # it.
private_key = RSA_KEY_512.private_key(backend)
ciphertext = private_key.public_key().encrypt(
- b'secure data',
+ b"secure data",
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
- )
+ label=None,
+ ),
)
private_key_alt = RSA_KEY_512_ALT.private_key(backend)
@@ -1596,8 +1681,8 @@ class TestRSADecryption(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
- )
+ label=None,
+ ),
)
@pytest.mark.supported(
@@ -1605,27 +1690,27 @@ class TestRSADecryption(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
+ label=None,
)
),
- skip_message="Does not support OAEP."
+ skip_message="Does not support OAEP.",
)
def test_invalid_oaep_decryption_data_to_large_for_modulus(self, backend):
key = RSA_KEY_2048_ALT.private_key(backend)
ciphertext = (
- b'\xb1ph\xc0\x0b\x1a|\xe6\xda\xea\xb5\xd7%\x94\x07\xf96\xfb\x96'
- b'\x11\x9b\xdc4\xea.-\x91\x80\x13S\x94\x04m\xe9\xc5/F\x1b\x9b:\\'
- b'\x1d\x04\x16ML\xae\xb32J\x01yuA\xbb\x83\x1c\x8f\xf6\xa5\xdbp\xcd'
- b'\nx\xc7\xf6\x15\xb2/\xdcH\xae\xe7\x13\x13by\r4t\x99\x0fc\x1f\xc1'
- b'\x1c\xb1\xdd\xc5\x08\xd1\xee\xa1XQ\xb8H@L5v\xc3\xaf\xf2\r\x97'
- b'\xed\xaa\xe7\xf1\xd4xai\xd3\x83\xd9\xaa9\xbfx\xe1\x87F \x01\xff'
- b'L\xccv}ae\xb3\xfa\xf2B\xb8\xf9\x04H\x94\x85\xcb\x86\xbb\\ghx!W31'
- b'\xc7;t\na_E\xc2\x16\xb0;\xa1\x18\t\x1b\xe1\xdb\x80>)\x15\xc6\x12'
- b'\xcb\xeeg`\x8b\x9b\x1b\x05y4\xb0\x84M6\xcd\xa1\x827o\xfd\x96\xba'
- b'Z#\x8d\xae\x01\xc9\xf2\xb6\xde\x89{8&eQ\x1e8\x03\x01#?\xb66\\'
- b'\xad.\xe9\xfa!\x95 c{\xcaz\xe0*\tP\r\x91\x9a)B\xb5\xadN\xf4$\x83'
- b'\t\xb5u\xab\x19\x99'
+ b"\xb1ph\xc0\x0b\x1a|\xe6\xda\xea\xb5\xd7%\x94\x07\xf96\xfb\x96"
+ b"\x11\x9b\xdc4\xea.-\x91\x80\x13S\x94\x04m\xe9\xc5/F\x1b\x9b:\\"
+ b"\x1d\x04\x16ML\xae\xb32J\x01yuA\xbb\x83\x1c\x8f\xf6\xa5\xdbp\xcd"
+ b"\nx\xc7\xf6\x15\xb2/\xdcH\xae\xe7\x13\x13by\r4t\x99\x0fc\x1f\xc1"
+ b"\x1c\xb1\xdd\xc5\x08\xd1\xee\xa1XQ\xb8H@L5v\xc3\xaf\xf2\r\x97"
+ b"\xed\xaa\xe7\xf1\xd4xai\xd3\x83\xd9\xaa9\xbfx\xe1\x87F \x01\xff"
+ b"L\xccv}ae\xb3\xfa\xf2B\xb8\xf9\x04H\x94\x85\xcb\x86\xbb\\ghx!W31"
+ b"\xc7;t\na_E\xc2\x16\xb0;\xa1\x18\t\x1b\xe1\xdb\x80>)\x15\xc6\x12"
+ b"\xcb\xeeg`\x8b\x9b\x1b\x05y4\xb0\x84M6\xcd\xa1\x827o\xfd\x96\xba"
+ b"Z#\x8d\xae\x01\xc9\xf2\xb6\xde\x89{8&eQ\x1e8\x03\x01#?\xb66\\"
+ b"\xad.\xe9\xfa!\x95 c{\xcaz\xe0*\tP\r\x91\x9a)B\xb5\xadN\xf4$\x83"
+ b"\t\xb5u\xab\x19\x99"
)
with pytest.raises(ValueError):
@@ -1634,8 +1719,8 @@ class TestRSADecryption(object):
padding.OAEP(
algorithm=hashes.SHA1(),
mgf=padding.MGF1(hashes.SHA1()),
- label=None
- )
+ label=None,
+ ),
)
def test_unsupported_oaep_mgf(self, backend):
@@ -1644,10 +1729,8 @@ class TestRSADecryption(object):
private_key.decrypt(
b"0" * 64,
padding.OAEP(
- mgf=DummyMGF(),
- algorithm=hashes.SHA1(),
- label=None
- )
+ mgf=DummyMGF(), algorithm=hashes.SHA1(), label=None
+ ),
)
@@ -1658,25 +1741,34 @@ class TestRSAEncryption(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
+ label=None,
)
),
- skip_message="Does not support OAEP."
+ skip_message="Does not support OAEP.",
)
@pytest.mark.parametrize(
("key_data", "pad"),
itertools.product(
- (RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027,
- RSA_KEY_1028, RSA_KEY_1029, RSA_KEY_1030, RSA_KEY_1031,
- RSA_KEY_1536, RSA_KEY_2048),
+ (
+ RSA_KEY_1024,
+ RSA_KEY_1025,
+ RSA_KEY_1026,
+ RSA_KEY_1027,
+ RSA_KEY_1028,
+ RSA_KEY_1029,
+ RSA_KEY_1030,
+ RSA_KEY_1031,
+ RSA_KEY_1536,
+ RSA_KEY_2048,
+ ),
[
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
+ label=None,
)
- ]
- )
+ ],
+ ),
)
def test_rsa_encrypt_oaep(self, key_data, pad, backend):
private_key = key_data.private_key(backend)
@@ -1684,7 +1776,7 @@ class TestRSAEncryption(object):
public_key = private_key.public_key()
ct = public_key.encrypt(pt, pad)
assert ct != pt
- assert len(ct) == math.ceil(public_key.key_size / 8.0)
+ assert len(ct) == (public_key.key_size + 7) // 8
recovered_pt = private_key.decrypt(ct, pad)
assert recovered_pt == pt
@@ -1693,39 +1785,44 @@ class TestRSAEncryption(object):
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA512(),
- label=None
+ label=None,
)
),
- skip_message="Does not support OAEP using SHA256 MGF1 and SHA512 hash."
+ skip_message=(
+ "Does not support OAEP using SHA256 MGF1 and SHA512 hash."
+ ),
)
@pytest.mark.parametrize(
("mgf1hash", "oaephash"),
- itertools.product([
- hashes.SHA1(),
- hashes.SHA224(),
- hashes.SHA256(),
- hashes.SHA384(),
- hashes.SHA512(),
- ], [
- hashes.SHA1(),
- hashes.SHA224(),
- hashes.SHA256(),
- hashes.SHA384(),
- hashes.SHA512(),
- ])
+ itertools.product(
+ [
+ hashes.SHA1(),
+ hashes.SHA224(),
+ hashes.SHA256(),
+ hashes.SHA384(),
+ hashes.SHA512(),
+ ],
+ [
+ hashes.SHA1(),
+ hashes.SHA224(),
+ hashes.SHA256(),
+ hashes.SHA384(),
+ hashes.SHA512(),
+ ],
+ ),
)
def test_rsa_encrypt_oaep_sha2(self, mgf1hash, oaephash, backend):
pad = padding.OAEP(
mgf=padding.MGF1(algorithm=mgf1hash),
algorithm=oaephash,
- label=None
+ label=None,
)
private_key = RSA_KEY_2048.private_key(backend)
pt = b"encrypt me using sha2 hashes!"
public_key = private_key.public_key()
ct = public_key.encrypt(pt, pad)
assert ct != pt
- assert len(ct) == math.ceil(public_key.key_size / 8.0)
+ assert len(ct) == (public_key.key_size + 7) // 8
recovered_pt = private_key.decrypt(ct, pad)
assert recovered_pt == pt
@@ -1733,16 +1830,25 @@ class TestRSAEncryption(object):
only_if=lambda backend: backend.rsa_padding_supported(
padding.PKCS1v15()
),
- skip_message="Does not support PKCS1v1.5."
+ skip_message="Does not support PKCS1v1.5.",
)
@pytest.mark.parametrize(
("key_data", "pad"),
itertools.product(
- (RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027,
- RSA_KEY_1028, RSA_KEY_1029, RSA_KEY_1030, RSA_KEY_1031,
- RSA_KEY_1536, RSA_KEY_2048),
- [padding.PKCS1v15()]
- )
+ (
+ RSA_KEY_1024,
+ RSA_KEY_1025,
+ RSA_KEY_1026,
+ RSA_KEY_1027,
+ RSA_KEY_1028,
+ RSA_KEY_1029,
+ RSA_KEY_1030,
+ RSA_KEY_1031,
+ RSA_KEY_1536,
+ RSA_KEY_2048,
+ ),
+ [padding.PKCS1v15()],
+ ),
)
def test_rsa_encrypt_pkcs1v15(self, key_data, pad, backend):
private_key = key_data.private_key(backend)
@@ -1750,42 +1856,45 @@ class TestRSAEncryption(object):
public_key = private_key.public_key()
ct = public_key.encrypt(pt, pad)
assert ct != pt
- assert len(ct) == math.ceil(public_key.key_size / 8.0)
+ assert len(ct) == (public_key.key_size + 7) // 8
recovered_pt = private_key.decrypt(ct, pad)
assert recovered_pt == pt
@pytest.mark.parametrize(
("key_data", "pad"),
itertools.product(
- (RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027,
- RSA_KEY_1028, RSA_KEY_1029, RSA_KEY_1030, RSA_KEY_1031,
- RSA_KEY_1536, RSA_KEY_2048),
+ (
+ RSA_KEY_1024,
+ RSA_KEY_1025,
+ RSA_KEY_1026,
+ RSA_KEY_1027,
+ RSA_KEY_1028,
+ RSA_KEY_1029,
+ RSA_KEY_1030,
+ RSA_KEY_1031,
+ RSA_KEY_1536,
+ RSA_KEY_2048,
+ ),
(
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
- label=None
+ label=None,
),
- padding.PKCS1v15()
- )
- )
+ padding.PKCS1v15(),
+ ),
+ ),
)
def test_rsa_encrypt_key_too_small(self, key_data, pad, backend):
private_key = key_data.private_key(backend)
public_key = private_key.public_key()
# Slightly smaller than the key size but not enough for padding.
with pytest.raises(ValueError):
- public_key.encrypt(
- b"\x00" * (private_key.key_size // 8 - 1),
- pad
- )
+ public_key.encrypt(b"\x00" * (private_key.key_size // 8 - 1), pad)
# Larger than the key size.
with pytest.raises(ValueError):
- public_key.encrypt(
- b"\x00" * (private_key.key_size // 8 + 5),
- pad
- )
+ public_key.encrypt(b"\x00" * (private_key.key_size // 8 + 5), pad)
def test_unsupported_padding(self, backend):
private_key = RSA_KEY_512.private_key(backend)
@@ -1804,10 +1913,8 @@ class TestRSAEncryption(object):
public_key.encrypt(
b"ciphertext",
padding.OAEP(
- mgf=DummyMGF(),
- algorithm=hashes.SHA1(),
- label=None
- )
+ mgf=DummyMGF(), algorithm=hashes.SHA1(), label=None
+ ),
)
@@ -1827,7 +1934,7 @@ class TestRSANumbers(object):
dmp1=1,
dmq1=1,
iqmp=2,
- public_numbers=public_numbers
+ public_numbers=public_numbers,
)
assert private_numbers.p == 3
@@ -1846,6 +1953,9 @@ class TestRSANumbers(object):
public_key = RSA_KEY_1024.public_numbers.public_key(backend)
assert public_key
+ public_key = rsa.RSAPublicNumbers(n=10, e=3).public_key(backend)
+ assert public_key
+
def test_public_numbers_invalid_types(self):
with pytest.raises(TypeError):
rsa.RSAPublicNumbers(e=None, n=15)
@@ -1863,18 +1973,20 @@ class TestRSANumbers(object):
(3, 5, 1, 1, None, 2, rsa.RSAPublicNumbers(e=1, n=15)),
(3, 5, 1, 1, 1, None, rsa.RSAPublicNumbers(e=1, n=15)),
(3, 5, 1, 1, 1, 2, None),
- ]
+ ],
)
- def test_private_numbers_invalid_types(self, p, q, d, dmp1, dmq1, iqmp,
- public_numbers):
+ def test_private_numbers_invalid_types(
+ self, p, q, d, dmp1, dmq1, iqmp, public_numbers
+ ):
with pytest.raises(TypeError):
rsa.RSAPrivateNumbers(
- p=p, q=q,
+ p=p,
+ q=q,
d=d,
dmp1=dmp1,
dmq1=dmq1,
iqmp=iqmp,
- public_numbers=public_numbers
+ public_numbers=public_numbers,
)
@pytest.mark.parametrize(
@@ -1884,7 +1996,7 @@ class TestRSANumbers(object):
(1, 15), # public_exponent < 3
(17, 15), # public_exponent > modulus
(14, 15), # public_exponent not odd
- ]
+ ],
)
def test_invalid_public_numbers_argument_values(self, e, n, backend):
# Start with public_exponent=7, modulus=15. Then change one value at a
@@ -1909,10 +2021,11 @@ class TestRSANumbers(object):
(3, 11, 3, 1, 3, 2, 6, 33), # public_exponent is not odd
(3, 11, 3, 2, 3, 2, 7, 33), # dmp1 is not odd
(3, 11, 3, 1, 4, 2, 7, 33), # dmq1 is not odd
- ]
+ ],
)
- def test_invalid_private_numbers_argument_values(self, p, q, d, dmp1, dmq1,
- iqmp, e, n, backend):
+ def test_invalid_private_numbers_argument_values(
+ self, p, q, d, dmp1, dmq1, iqmp, e, n, backend
+ ):
# Start with p=3, q=11, private_exponent=3, public_exponent=7,
# modulus=33, dmp1=1, dmq1=3, iqmp=2. Then change one value at
# a time to test the bounds.
@@ -1925,10 +2038,7 @@ class TestRSANumbers(object):
dmp1=dmp1,
dmq1=dmq1,
iqmp=iqmp,
- public_numbers=rsa.RSAPublicNumbers(
- e=e,
- n=n
- )
+ public_numbers=rsa.RSAPublicNumbers(e=e, n=n),
).private_key(backend)
def test_public_number_repr(self):
@@ -2004,18 +2114,19 @@ class TestRSANumbersEquality(object):
class TestRSAPrimeFactorRecovery(object):
@pytest.mark.parametrize(
"vector",
- _flatten_pkcs1_examples(load_vectors_from_file(
- os.path.join(
- "asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"),
- load_pkcs1_vectors
- ))
+ _flatten_pkcs1_examples(
+ load_vectors_from_file(
+ os.path.join("asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"),
+ load_pkcs1_vectors,
+ )
+ ),
)
def test_recover_prime_factors(self, vector):
private, public, example = vector
p, q = rsa.rsa_recover_prime_factors(
private["modulus"],
private["public_exponent"],
- private["private_exponent"]
+ private["private_exponent"],
)
# Unfortunately there is no convention on which prime should be p
# and which one q. The function we use always makes p > q, but the
@@ -2037,22 +2148,23 @@ class TestRSAPrivateKeySerialization(object):
itertools.product(
[
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.PrivateFormat.PKCS8
+ serialization.PrivateFormat.PKCS8,
],
[
b"s",
b"longerpassword",
b"!*$&(@#$*&($T@%_somesymbols",
b"\x01" * 1000,
- ]
- )
+ ],
+ ),
)
def test_private_bytes_encrypted_pem(self, backend, fmt, password):
+ skip_fips_traditional_openssl(backend, fmt)
key = RSA_KEY_2048.private_key(backend)
serialized = key.private_bytes(
serialization.Encoding.PEM,
fmt,
- serialization.BestAvailableEncryption(password)
+ serialization.BestAvailableEncryption(password),
)
loaded_key = serialization.load_pem_private_key(
serialized, password, backend
@@ -2068,7 +2180,7 @@ class TestRSAPrivateKeySerialization(object):
(serialization.Encoding.DER, serialization.PrivateFormat.Raw),
(serialization.Encoding.Raw, serialization.PrivateFormat.Raw),
(serialization.Encoding.X962, serialization.PrivateFormat.PKCS8),
- ]
+ ],
)
def test_private_bytes_rejects_invalid(self, encoding, fmt, backend):
key = RSA_KEY_2048.private_key(backend)
@@ -2081,15 +2193,15 @@ class TestRSAPrivateKeySerialization(object):
[serialization.PrivateFormat.PKCS8, b"s"],
[serialization.PrivateFormat.PKCS8, b"longerpassword"],
[serialization.PrivateFormat.PKCS8, b"!*$&(@#$*&($T@%_somesymbol"],
- [serialization.PrivateFormat.PKCS8, b"\x01" * 1000]
- ]
+ [serialization.PrivateFormat.PKCS8, b"\x01" * 1000],
+ ],
)
def test_private_bytes_encrypted_der(self, backend, fmt, password):
key = RSA_KEY_2048.private_key(backend)
serialized = key.private_bytes(
serialization.Encoding.DER,
fmt,
- serialization.BestAvailableEncryption(password)
+ serialization.BestAvailableEncryption(password),
)
loaded_key = serialization.load_der_private_key(
serialized, password, backend
@@ -2104,27 +2216,28 @@ class TestRSAPrivateKeySerialization(object):
[
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
],
[
serialization.Encoding.DER,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
],
[
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
],
[
serialization.Encoding.DER,
serialization.PrivateFormat.PKCS8,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
],
- ]
+ ],
)
- def test_private_bytes_unencrypted(self, backend, encoding, fmt,
- loader_func):
+ def test_private_bytes_unencrypted(
+ self, backend, encoding, fmt, loader_func
+ ):
key = RSA_KEY_2048.private_key(backend)
serialized = key.private_bytes(
encoding, fmt, serialization.NoEncryption()
@@ -2134,6 +2247,9 @@ class TestRSAPrivateKeySerialization(object):
priv_num = key.private_numbers()
assert loaded_priv_num == priv_num
+ @pytest.mark.skip_fips(
+ reason="Traditional OpenSSL key format is not supported in FIPS mode."
+ )
@pytest.mark.parametrize(
("key_path", "encoding", "loader_func"),
[
@@ -2141,17 +2257,17 @@ class TestRSAPrivateKeySerialization(object):
os.path.join(
"asymmetric",
"Traditional_OpenSSL_Serialization",
- "testrsa.pem"
+ "testrsa.pem",
),
serialization.Encoding.PEM,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
],
[
os.path.join("asymmetric", "DER_Serialization", "testrsa.der"),
serialization.Encoding.DER,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
],
- ]
+ ],
)
def test_private_bytes_traditional_openssl_unencrypted(
self, backend, key_path, encoding, loader_func
@@ -2163,7 +2279,7 @@ class TestRSAPrivateKeySerialization(object):
serialized = key.private_bytes(
encoding,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
assert serialized == key_bytes
@@ -2173,7 +2289,7 @@ class TestRSAPrivateKeySerialization(object):
key.private_bytes(
serialization.Encoding.DER,
serialization.PrivateFormat.TraditionalOpenSSL,
- serialization.BestAvailableEncryption(b"password")
+ serialization.BestAvailableEncryption(b"password"),
)
def test_private_bytes_invalid_encoding(self, backend):
@@ -2182,7 +2298,7 @@ class TestRSAPrivateKeySerialization(object):
key.private_bytes(
"notencoding",
serialization.PrivateFormat.PKCS8,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_private_bytes_invalid_format(self, backend):
@@ -2191,7 +2307,7 @@ class TestRSAPrivateKeySerialization(object):
key.private_bytes(
serialization.Encoding.PEM,
"invalidformat",
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_private_bytes_invalid_encryption_algorithm(self, backend):
@@ -2200,7 +2316,7 @@ class TestRSAPrivateKeySerialization(object):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- "notanencalg"
+ "notanencalg",
)
def test_private_bytes_unsupported_encryption_type(self, backend):
@@ -2209,7 +2325,7 @@ class TestRSAPrivateKeySerialization(object):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
- DummyKeySerializationEncryption()
+ DummyKeySerializationEncryption(),
)
@@ -2224,30 +2340,34 @@ class TestRSAPEMPublicKeySerialization(object):
serialization.load_pem_public_key,
serialization.Encoding.PEM,
serialization.PublicFormat.PKCS1,
- ), (
+ ),
+ (
os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.der"),
serialization.load_der_public_key,
serialization.Encoding.DER,
serialization.PublicFormat.PKCS1,
- ), (
+ ),
+ (
os.path.join("asymmetric", "PKCS8", "unenc-rsa-pkcs8.pub.pem"),
serialization.load_pem_public_key,
serialization.Encoding.PEM,
serialization.PublicFormat.SubjectPublicKeyInfo,
- ), (
+ ),
+ (
os.path.join(
"asymmetric",
"DER_Serialization",
- "unenc-rsa-pkcs8.pub.der"
+ "unenc-rsa-pkcs8.pub.der",
),
serialization.load_der_public_key,
serialization.Encoding.DER,
serialization.PublicFormat.SubjectPublicKeyInfo,
- )
- ]
+ ),
+ ],
)
- def test_public_bytes_match(self, key_path, loader_func, encoding, format,
- backend):
+ def test_public_bytes_match(
+ self, key_path, loader_func, encoding, format, backend
+ ):
key_bytes = load_vectors_from_file(
key_path, lambda pemfile: pemfile.read(), mode="rb"
)
@@ -2258,7 +2378,8 @@ class TestRSAPEMPublicKeySerialization(object):
def test_public_bytes_openssh(self, backend):
key_bytes = load_vectors_from_file(
os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.pem"),
- lambda pemfile: pemfile.read(), mode="rb"
+ lambda pemfile: pemfile.read(),
+ mode="rb",
)
key = serialization.load_pem_public_key(key_bytes, backend)
@@ -2306,22 +2427,25 @@ class TestRSAPEMPublicKeySerialization(object):
[
(
serialization.Encoding.Raw,
- serialization.PublicFormat.SubjectPublicKeyInfo
+ serialization.PublicFormat.SubjectPublicKeyInfo,
),
(serialization.Encoding.Raw, serialization.PublicFormat.PKCS1),
- ] + list(itertools.product(
- [
- serialization.Encoding.Raw,
- serialization.Encoding.X962,
- serialization.Encoding.PEM,
- serialization.Encoding.DER
- ],
- [
- serialization.PublicFormat.Raw,
- serialization.PublicFormat.UncompressedPoint,
- serialization.PublicFormat.CompressedPoint
- ]
- ))
+ ]
+ + list(
+ itertools.product(
+ [
+ serialization.Encoding.Raw,
+ serialization.Encoding.X962,
+ serialization.Encoding.PEM,
+ serialization.Encoding.DER,
+ ],
+ [
+ serialization.PublicFormat.Raw,
+ serialization.PublicFormat.UncompressedPoint,
+ serialization.PublicFormat.CompressedPoint,
+ ],
+ )
+ ),
)
def test_public_bytes_rejects_invalid(self, encoding, fmt, backend):
key = RSA_KEY_2048.private_key(backend).public_key()
diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py
index 8f3a14edc..52e7e1538 100644
--- a/tests/hazmat/primitives/test_scrypt.py
+++ b/tests/hazmat/primitives/test_scrypt.py
@@ -10,7 +10,9 @@ import os
import pytest
from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, UnsupportedAlgorithm
+ AlreadyFinalized,
+ InvalidKey,
+ UnsupportedAlgorithm,
)
from cryptography.hazmat.backends.interfaces import ScryptBackend
from cryptography.hazmat.primitives.kdf.scrypt import Scrypt, _MEM_LIMIT
@@ -18,7 +20,8 @@ from cryptography.hazmat.primitives.kdf.scrypt import Scrypt, _MEM_LIMIT
from tests.utils import load_nist_vectors, load_vectors_from_file
vectors = load_vectors_from_file(
- os.path.join("KDF", "scrypt.txt"), load_nist_vectors)
+ os.path.join("KDF", "scrypt.txt"), load_nist_vectors
+)
def _skip_if_memory_limited(memory_limit, params):
@@ -29,8 +32,10 @@ def _skip_if_memory_limited(memory_limit, params):
vlen = 32 * int(params["r"]) * (int(params["n"]) + 2) * 4
memory_required = blen + vlen
if memory_limit < memory_required:
- pytest.skip("Test exceeds Scrypt memory limit. "
- "This is likely a 32-bit platform.")
+ pytest.skip(
+ "Test exceeds Scrypt memory limit. "
+ "This is likely a 32-bit platform."
+ )
def test_memory_limit_skip():
@@ -53,8 +58,14 @@ class TestScrypt(object):
salt = params["salt"]
derived_key = params["derived_key"]
- scrypt = Scrypt(salt, length, work_factor, block_size,
- parallelization_factor, backend)
+ scrypt = Scrypt(
+ salt,
+ length,
+ work_factor,
+ block_size,
+ parallelization_factor,
+ backend,
+ )
assert binascii.hexlify(scrypt.derive(password)) == derived_key
def test_unsupported_backend(self):
@@ -66,8 +77,14 @@ class TestScrypt(object):
backend = object()
with pytest.raises(UnsupportedAlgorithm):
- Scrypt(salt, length, work_factor, block_size,
- parallelization_factor, backend)
+ Scrypt(
+ salt,
+ length,
+ work_factor,
+ block_size,
+ parallelization_factor,
+ backend,
+ )
def test_salt_not_bytes(self, backend):
work_factor = 1024
@@ -77,8 +94,14 @@ class TestScrypt(object):
salt = 1
with pytest.raises(TypeError):
- Scrypt(salt, length, work_factor, block_size,
- parallelization_factor, backend)
+ Scrypt(
+ salt,
+ length,
+ work_factor,
+ block_size,
+ parallelization_factor,
+ backend,
+ )
def test_scrypt_malloc_failure(self, backend):
password = b"NaCl"
@@ -88,8 +111,14 @@ class TestScrypt(object):
length = 64
salt = b"NaCl"
- scrypt = Scrypt(salt, length, work_factor, block_size,
- parallelization_factor, backend)
+ scrypt = Scrypt(
+ salt,
+ length,
+ work_factor,
+ block_size,
+ parallelization_factor,
+ backend,
+ )
with pytest.raises(MemoryError):
scrypt.derive(password)
@@ -102,8 +131,14 @@ class TestScrypt(object):
length = 64
salt = b"NaCl"
- scrypt = Scrypt(salt, length, work_factor, block_size,
- parallelization_factor, backend)
+ scrypt = Scrypt(
+ salt,
+ length,
+ work_factor,
+ block_size,
+ parallelization_factor,
+ backend,
+ )
with pytest.raises(TypeError):
scrypt.derive(password)
@@ -116,10 +151,16 @@ class TestScrypt(object):
length = 10
salt = b"NaCl"
- scrypt = Scrypt(salt, length, work_factor, block_size,
- parallelization_factor, backend)
+ scrypt = Scrypt(
+ salt,
+ length,
+ work_factor,
+ block_size,
+ parallelization_factor,
+ backend,
+ )
- assert scrypt.derive(password) == b'\xf4\x92\x86\xb2\x06\x0c\x848W\x87'
+ assert scrypt.derive(password) == b"\xf4\x92\x86\xb2\x06\x0c\x848W\x87"
@pytest.mark.parametrize("params", vectors)
def test_verify(self, backend, params):
@@ -132,8 +173,14 @@ class TestScrypt(object):
salt = params["salt"]
derived_key = params["derived_key"]
- scrypt = Scrypt(salt, length, work_factor, block_size,
- parallelization_factor, backend)
+ scrypt = Scrypt(
+ salt,
+ length,
+ work_factor,
+ block_size,
+ parallelization_factor,
+ backend,
+ )
assert scrypt.verify(password, binascii.unhexlify(derived_key)) is None
def test_invalid_verify(self, backend):
@@ -145,8 +192,14 @@ class TestScrypt(object):
salt = b"NaCl"
derived_key = b"fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773"
- scrypt = Scrypt(salt, length, work_factor, block_size,
- parallelization_factor, backend)
+ scrypt = Scrypt(
+ salt,
+ length,
+ work_factor,
+ block_size,
+ parallelization_factor,
+ backend,
+ )
with pytest.raises(InvalidKey):
scrypt.verify(password, binascii.unhexlify(derived_key))
@@ -159,8 +212,14 @@ class TestScrypt(object):
length = 64
salt = b"NaCl"
- scrypt = Scrypt(salt, length, work_factor, block_size,
- parallelization_factor, backend)
+ scrypt = Scrypt(
+ salt,
+ length,
+ work_factor,
+ block_size,
+ parallelization_factor,
+ backend,
+ )
scrypt.derive(password)
with pytest.raises(AlreadyFinalized):
scrypt.derive(password)
diff --git a/tests/hazmat/primitives/test_seed.py b/tests/hazmat/primitives/test_seed.py
index 29cae4fe9..66da97836 100644
--- a/tests/hazmat/primitives/test_seed.py
+++ b/tests/hazmat/primitives/test_seed.py
@@ -24,7 +24,7 @@ from ...utils import load_nist_vectors
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestSEEDModeECB(object):
- test_ECB = generate_encrypt_test(
+ test_ecb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "SEED"),
["rfc-4269.txt"],
@@ -41,12 +41,12 @@ class TestSEEDModeECB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestSEEDModeCBC(object):
- test_CBC = generate_encrypt_test(
+ test_cbc = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "SEED"),
["rfc-4196.txt"],
lambda key, **kwargs: algorithms.SEED(binascii.unhexlify((key))),
- lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv))
+ lambda iv, **kwargs: modes.CBC(binascii.unhexlify(iv)),
)
@@ -58,12 +58,12 @@ class TestSEEDModeCBC(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestSEEDModeOFB(object):
- test_OFB = generate_encrypt_test(
+ test_ofb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "SEED"),
["seed-ofb.txt"],
lambda key, **kwargs: algorithms.SEED(binascii.unhexlify((key))),
- lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv))
+ lambda iv, **kwargs: modes.OFB(binascii.unhexlify(iv)),
)
@@ -75,10 +75,10 @@ class TestSEEDModeOFB(object):
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
class TestSEEDModeCFB(object):
- test_CFB = generate_encrypt_test(
+ test_cfb = generate_encrypt_test(
load_nist_vectors,
os.path.join("ciphers", "SEED"),
["seed-cfb.txt"],
lambda key, **kwargs: algorithms.SEED(binascii.unhexlify((key))),
- lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv))
+ lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)),
)
diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py
index 5dd724894..32debd46c 100644
--- a/tests/hazmat/primitives/test_serialization.py
+++ b/tests/hazmat/primitives/test_serialization.py
@@ -11,27 +11,58 @@ import textwrap
import pytest
-from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+import six
+
+from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.backends.interfaces import (
- DERSerializationBackend, DSABackend, EllipticCurveBackend,
- PEMSerializationBackend, RSABackend
+ DERSerializationBackend,
+ DSABackend,
+ EllipticCurveBackend,
+ PEMSerializationBackend,
+ RSABackend,
+)
+from cryptography.hazmat.primitives.asymmetric import (
+ dsa,
+ ec,
+ ed25519,
+ ed448,
+ rsa,
+ x25519,
+ x448,
)
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
from cryptography.hazmat.primitives.serialization import (
- BestAvailableEncryption, Encoding, NoEncryption,
- PrivateFormat, PublicFormat,
- load_der_parameters, load_der_private_key,
- load_der_public_key, load_pem_parameters, load_pem_private_key,
- load_pem_public_key, load_ssh_public_key
+ BestAvailableEncryption,
+ Encoding,
+ NoEncryption,
+ PrivateFormat,
+ PublicFormat,
+ load_der_parameters,
+ load_der_private_key,
+ load_der_public_key,
+ load_pem_parameters,
+ load_pem_private_key,
+ load_pem_public_key,
+ load_ssh_private_key,
+ load_ssh_public_key,
+ ssh,
)
from .test_ec import _skip_curve_unsupported
from .utils import (
- _check_dsa_private_numbers, _check_rsa_private_numbers,
- load_vectors_from_file
+ _check_dsa_private_numbers,
+ _check_rsa_private_numbers,
+ load_vectors_from_file,
)
-from ...utils import raises_unsupported_algorithm
+from ...doubles import DummyKeySerializationEncryption
+
+
+def _skip_fips_format(key_path, password, backend):
+ if backend._fips_enabled:
+ if key_path[0] == "Traditional_OpenSSL_Serialization":
+ pytest.skip("Traditional OpenSSL format blocked in FIPS mode")
+ if key_path[0] == "PEM_Serialization" and password is not None:
+ pytest.skip("Encrypted PEM_Serialization blocked in FIPS mode")
class TestBufferProtocolSerialization(object):
@@ -43,12 +74,13 @@ class TestBufferProtocolSerialization(object):
(["DER_Serialization", "enc2-rsa-pkcs8.der"], bytearray(b"baz")),
(["DER_Serialization", "unenc-rsa-pkcs8.der"], None),
(["DER_Serialization", "testrsa.der"], None),
- ]
+ ],
)
def test_load_der_rsa_private_key(self, key_path, password, backend):
data = load_vectors_from_file(
os.path.join("asymmetric", *key_path),
- lambda derfile: derfile.read(), mode="rb"
+ lambda derfile: derfile.read(),
+ mode="rb",
)
key = load_der_private_key(bytearray(data), password, backend)
assert key
@@ -61,21 +93,23 @@ class TestBufferProtocolSerialization(object):
[
(
["PEM_Serialization", "rsa_private_key.pem"],
- bytearray(b"123456")
+ bytearray(b"123456"),
),
(["PKCS8", "unenc-rsa-pkcs8.pem"], None),
(["PKCS8", "enc-rsa-pkcs8.pem"], bytearray(b"foobar")),
(["PKCS8", "enc2-rsa-pkcs8.pem"], bytearray(b"baz")),
(
["Traditional_OpenSSL_Serialization", "key1.pem"],
- bytearray(b"123456")
+ bytearray(b"123456"),
),
- ]
+ ],
)
def test_load_pem_rsa_private_key(self, key_path, password, backend):
+ _skip_fips_format(key_path, password, backend)
data = load_vectors_from_file(
os.path.join("asymmetric", *key_path),
- lambda pemfile: pemfile.read(), mode="rb"
+ lambda pemfile: pemfile.read(),
+ mode="rb",
)
key = load_pem_private_key(bytearray(data), password, backend)
assert key
@@ -93,7 +127,7 @@ class TestDERSerialization(object):
(["DER_Serialization", "enc2-rsa-pkcs8.der"], b"baz"),
(["DER_Serialization", "unenc-rsa-pkcs8.der"], None),
(["DER_Serialization", "testrsa.der"], None),
- ]
+ ],
)
def test_load_der_rsa_private_key(self, key_path, password, backend):
key = load_vectors_from_file(
@@ -101,7 +135,7 @@ class TestDERSerialization(object):
lambda derfile: load_der_private_key(
derfile.read(), password, backend
),
- mode="rb"
+ mode="rb",
)
assert key
assert isinstance(key, rsa.RSAPrivateKey)
@@ -115,7 +149,7 @@ class TestDERSerialization(object):
(["DER_Serialization", "dsa.1024.der"], None),
(["DER_Serialization", "dsa.2048.der"], None),
(["DER_Serialization", "dsa.3072.der"], None),
- ]
+ ],
)
def test_load_der_dsa_private_key(self, key_path, password, backend):
key = load_vectors_from_file(
@@ -123,17 +157,14 @@ class TestDERSerialization(object):
lambda derfile: load_der_private_key(
derfile.read(), password, backend
),
- mode="rb"
+ mode="rb",
)
assert key
assert isinstance(key, dsa.DSAPrivateKey)
_check_dsa_private_numbers(key.private_numbers())
@pytest.mark.parametrize(
- "key_path",
- [
- ["DER_Serialization", "enc-rsa-pkcs8.der"],
- ]
+ "key_path", [["DER_Serialization", "enc-rsa-pkcs8.der"]]
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
def test_password_not_bytes(self, key_path, backend):
@@ -146,7 +177,7 @@ class TestDERSerialization(object):
lambda derfile: load_der_private_key(
derfile.read(), password, backend
),
- mode="rb"
+ mode="rb",
)
@pytest.mark.parametrize(
@@ -154,7 +185,7 @@ class TestDERSerialization(object):
[
(["DER_Serialization", "ec_private_key.der"], None),
(["DER_Serialization", "ec_private_key_encrypted.der"], b"123456"),
- ]
+ ],
)
@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
def test_load_der_ec_private_key(self, key_path, password, backend):
@@ -164,7 +195,7 @@ class TestDERSerialization(object):
lambda derfile: load_der_private_key(
derfile.read(), password, backend
),
- mode="rb"
+ mode="rb",
)
assert key
@@ -173,10 +204,7 @@ class TestDERSerialization(object):
assert key.curve.key_size == 256
@pytest.mark.parametrize(
- "key_path",
- [
- ["DER_Serialization", "enc-rsa-pkcs8.der"],
- ]
+ "key_path", [["DER_Serialization", "enc-rsa-pkcs8.der"]]
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
def test_wrong_password(self, key_path, backend):
@@ -189,14 +217,11 @@ class TestDERSerialization(object):
lambda derfile: load_der_private_key(
derfile.read(), password, backend
),
- mode="rb"
+ mode="rb",
)
@pytest.mark.parametrize(
- "key_path",
- [
- ["DER_Serialization", "unenc-rsa-pkcs8.der"]
- ]
+ "key_path", [["DER_Serialization", "unenc-rsa-pkcs8.der"]]
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
def test_unused_password(self, key_path, backend):
@@ -209,17 +234,14 @@ class TestDERSerialization(object):
lambda derfile: load_der_private_key(
derfile.read(), password, backend
),
- mode="rb"
+ mode="rb",
)
@pytest.mark.parametrize(
("key_path", "password"),
itertools.product(
- [
- ["DER_Serialization", "enc-rsa-pkcs8.der"],
- ],
- [b"", None]
- )
+ [["DER_Serialization", "enc-rsa-pkcs8.der"]], [b"", None]
+ ),
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
def test_missing_password(self, key_path, password, backend):
@@ -231,16 +253,14 @@ class TestDERSerialization(object):
lambda derfile: load_der_private_key(
derfile.read(), password, backend
),
- mode="rb"
+ mode="rb",
)
def test_wrong_format(self, backend):
key_data = b"---- NOT A KEY ----\n"
with pytest.raises(ValueError):
- load_der_private_key(
- key_data, None, backend
- )
+ load_der_private_key(key_data, None, backend)
with pytest.raises(ValueError):
load_der_private_key(
@@ -249,7 +269,8 @@ class TestDERSerialization(object):
def test_corrupt_der_pkcs8(self, backend):
# unenc-rsa-pkcs8 with a bunch of data missing.
- key_data = textwrap.dedent("""\
+ key_data = textwrap.dedent(
+ """\
MIICdQIBADALBgkqhkiG9w0BAQEEggJhMIICXQIBAAKBgQC7JHoJfg6yNzLMOWet
8Z49a4KD0dCspMAYvo2YAMB7/wdEycocujbhJ2n/seONi+5XqTqqFkM5VBl8rmkk
FPZk/7x0xmdsTPECSWnHK+HhoaNDFPR3j8jQhVo1laxiqcEhAHegi5cwtFosuJAv
@@ -263,13 +284,12 @@ class TestDERSerialization(object):
z+KOpdpPRR5TQmbEMEspjsFpFymMiuYPgmihQbO2cJl1qScY5OkCQQCJ6m5tcN8l
Xxg/SNpjEIv+qAyUD96XVlOJlOIeLHQ8kYE0C6ZA+MsqYIzgAreJk88Yn0lU/X0/
mu/UpE/BRZmR
- """).encode()
+ """
+ ).encode()
bad_der = base64.b64decode(b"".join(key_data.splitlines()))
with pytest.raises(ValueError):
- load_der_private_key(
- bad_der, None, backend
- )
+ load_der_private_key(bad_der, None, backend)
with pytest.raises(ValueError):
load_der_private_key(
@@ -278,14 +298,16 @@ class TestDERSerialization(object):
def test_corrupt_traditional_format_der(self, backend):
# privkey with a bunch of data missing.
- key_data = textwrap.dedent("""\
+ key_data = textwrap.dedent(
+ """\
MIIBPAIBAAJBAKrbeqkuRk8VcRmWFmtP+LviMB3+6dizWW3DwaffznyHGAFwUJ/I
Tv0XtbsCyl3QoyKGhrOAy3RvPK5M38iuXT0CAwEAAQJAZ3cnzaHXM/bxGaR5CR1R
rD1qFBAVfoQFiOH9uPJgMaoAuoQEisPHVcZDKcOv4wEg6/TInAIXBnEigtqvRzuy
mvcpHZwQJdmdHHkGKAs37Dfxi67HbkUCIQCeZGliHXFa071Fp06ZeWlR2ADonTZz
rJBhdTe0v5pCeQIhAIZfkiGgGBX4cIuuckzEm43g9WMUjxP/0GlK39vIyihxAiEA
mymehFRT0MvqW5xAKAx7Pgkt8HVKwVhc2LwGKHE0DZM=
- """).encode()
+ """
+ ).encode()
bad_der = base64.b64decode(b"".join(key_data.splitlines()))
with pytest.raises(ValueError):
@@ -300,20 +322,20 @@ class TestDERSerialization(object):
"key_file",
[
os.path.join(
- "asymmetric", "DER_Serialization", "unenc-rsa-pkcs8.pub.der"),
+ "asymmetric", "DER_Serialization", "unenc-rsa-pkcs8.pub.der"
+ ),
os.path.join(
- "asymmetric", "DER_Serialization", "rsa_public_key.der"),
+ "asymmetric", "DER_Serialization", "rsa_public_key.der"
+ ),
os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.der"),
- ]
+ ],
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
def test_load_der_rsa_public_key(self, key_file, backend):
key = load_vectors_from_file(
key_file,
- lambda derfile: load_der_public_key(
- derfile.read(), backend
- ),
- mode="rb"
+ lambda derfile: load_der_public_key(derfile.read(), backend),
+ mode="rb",
)
assert key
assert isinstance(key, rsa.RSAPublicKey)
@@ -328,19 +350,19 @@ class TestDERSerialization(object):
"key_file",
[
os.path.join(
- "asymmetric", "DER_Serialization", "unenc-dsa-pkcs8.pub.der"),
+ "asymmetric", "DER_Serialization", "unenc-dsa-pkcs8.pub.der"
+ ),
os.path.join(
- "asymmetric", "DER_Serialization", "dsa_public_key.der"),
- ]
+ "asymmetric", "DER_Serialization", "dsa_public_key.der"
+ ),
+ ],
)
@pytest.mark.requires_backend_interface(interface=DSABackend)
def test_load_der_dsa_public_key(self, key_file, backend):
key = load_vectors_from_file(
key_file,
- lambda derfile: load_der_public_key(
- derfile.read(), backend
- ),
- mode="rb"
+ lambda derfile: load_der_public_key(derfile.read(), backend),
+ mode="rb",
)
assert key
assert isinstance(key, dsa.DSAPublicKey)
@@ -350,12 +372,10 @@ class TestDERSerialization(object):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = load_vectors_from_file(
os.path.join(
- "asymmetric", "DER_Serialization",
- "ec_public_key.der"),
- lambda derfile: load_der_public_key(
- derfile.read(), backend
+ "asymmetric", "DER_Serialization", "ec_public_key.der"
),
- mode="rb"
+ lambda derfile: load_der_public_key(derfile.read(), backend),
+ mode="rb",
)
assert key
assert isinstance(key, ec.EllipticCurvePublicKey)
@@ -366,9 +386,7 @@ class TestDERSerialization(object):
param_data = b"---- NOT A KEY ----\n"
with pytest.raises(ValueError):
- load_der_parameters(
- param_data, backend
- )
+ load_der_parameters(param_data, backend)
@pytest.mark.requires_backend_interface(interface=PEMSerializationBackend)
@@ -393,16 +411,19 @@ class TestPEMSerialization(object):
(["Traditional_OpenSSL_Serialization", "key1.pem"], b"123456"),
(["Traditional_OpenSSL_Serialization", "key2.pem"], b"a123456"),
(["Traditional_OpenSSL_Serialization", "testrsa.pem"], None),
- (["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
- b"password"),
- ]
+ (
+ ["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
+ b"password",
+ ),
+ ],
)
def test_load_pem_rsa_private_key(self, key_file, password, backend):
+ _skip_fips_format(key_file, password, backend)
key = load_vectors_from_file(
os.path.join("asymmetric", *key_file),
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), password, backend
- )
+ ),
)
assert key
@@ -417,14 +438,15 @@ class TestPEMSerialization(object):
(["Traditional_OpenSSL_Serialization", "dsa.3072.pem"], None),
(["PKCS8", "unenc-dsa-pkcs8.pem"], None),
(["PEM_Serialization", "dsa_private_key.pem"], b"123456"),
- ]
+ ],
)
def test_load_dsa_private_key(self, key_path, password, backend):
+ _skip_fips_format(key_path, password, backend)
key = load_vectors_from_file(
os.path.join("asymmetric", *key_path),
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), password, backend
- )
+ ),
)
assert key
assert isinstance(key, dsa.DSAPrivateKey)
@@ -437,16 +459,17 @@ class TestPEMSerialization(object):
(["PKCS8", "ec_private_key_encrypted.pem"], b"123456"),
(["PEM_Serialization", "ec_private_key.pem"], None),
(["PEM_Serialization", "ec_private_key_encrypted.pem"], b"123456"),
- ]
+ ],
)
@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
def test_load_pem_ec_private_key(self, key_path, password, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
+ _skip_fips_format(key_path, password, backend)
key = load_vectors_from_file(
os.path.join("asymmetric", *key_path),
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), password, backend
- )
+ ),
)
assert key
@@ -459,16 +482,17 @@ class TestPEMSerialization(object):
[
os.path.join("asymmetric", "PKCS8", "unenc-rsa-pkcs8.pub.pem"),
os.path.join(
- "asymmetric", "PEM_Serialization", "rsa_public_key.pem"),
+ "asymmetric", "PEM_Serialization", "rsa_public_key.pem"
+ ),
os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.pem"),
- ]
+ ],
)
def test_load_pem_rsa_public_key(self, key_file, backend):
key = load_vectors_from_file(
key_file,
lambda pemfile: load_pem_public_key(
pemfile.read().encode(), backend
- )
+ ),
)
assert key
assert isinstance(key, rsa.RSAPublicKey)
@@ -480,16 +504,16 @@ class TestPEMSerialization(object):
[
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"),
os.path.join(
- "asymmetric", "PEM_Serialization",
- "dsa_public_key.pem"),
- ]
+ "asymmetric", "PEM_Serialization", "dsa_public_key.pem"
+ ),
+ ],
)
def test_load_pem_dsa_public_key(self, key_file, backend):
key = load_vectors_from_file(
key_file,
lambda pemfile: load_pem_public_key(
pemfile.read().encode(), backend
- )
+ ),
)
assert key
assert isinstance(key, dsa.DSAPublicKey)
@@ -499,66 +523,70 @@ class TestPEMSerialization(object):
_skip_curve_unsupported(backend, ec.SECP256R1())
key = load_vectors_from_file(
os.path.join(
- "asymmetric", "PEM_Serialization",
- "ec_public_key.pem"),
+ "asymmetric", "PEM_Serialization", "ec_public_key.pem"
+ ),
lambda pemfile: load_pem_public_key(
pemfile.read().encode(), backend
- )
+ ),
)
assert key
assert isinstance(key, ec.EllipticCurvePublicKey)
assert key.curve.name == "secp256r1"
assert key.curve.key_size == 256
+ @pytest.mark.skip_fips(
+ reason="Traditional OpenSSL format blocked in FIPS mode"
+ )
def test_rsa_traditional_encrypted_values(self, backend):
pkey = load_vectors_from_file(
os.path.join(
- "asymmetric", "Traditional_OpenSSL_Serialization", "key1.pem"),
+ "asymmetric", "Traditional_OpenSSL_Serialization", "key1.pem"
+ ),
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), b"123456", backend
- )
+ ),
)
assert pkey
numbers = pkey.private_numbers()
assert numbers.p == int(
"fb7d316fc51531b36d93adaefaf52db6ad5beb793d37c4cf9dfc1ddd17cfbafb",
- 16
+ 16,
)
assert numbers.q == int(
"df98264e646de9a0fbeab094e31caad5bc7adceaaae3c800ca0275dd4bb307f5",
- 16
+ 16,
)
assert numbers.d == int(
"db4848c36f478dd5d38f35ae519643b6b810d404bcb76c00e44015e56ca1cab0"
"7bb7ae91f6b4b43fcfc82a47d7ed55b8c575152116994c2ce5325ec24313b911",
- 16
+ 16,
)
assert numbers.dmp1 == int(
"ce997f967192c2bcc3853186f1559fd355c190c58ddc15cbf5de9b6df954c727",
- 16
+ 16,
)
assert numbers.dmq1 == int(
"b018a57ab20ffaa3862435445d863369b852cf70a67c55058213e3fe10e3848d",
- 16
+ 16,
)
assert numbers.iqmp == int(
"6a8d830616924f5cf2d1bc1973f97fde6b63e052222ac7be06aa2532d10bac76",
- 16
+ 16,
)
assert numbers.public_numbers.e == 65537
assert numbers.public_numbers.n == int(
"dba786074f2f0350ce1d99f5aed5b520cfe0deb5429ec8f2a88563763f566e77"
"9814b7c310e5326edae31198eed439b845dd2db99eaa60f5c16a43f4be6bcf37",
- 16
+ 16,
)
@pytest.mark.parametrize(
"key_path",
[
["Traditional_OpenSSL_Serialization", "testrsa.pem"],
- ["PKCS8", "unenc-rsa-pkcs8.pem"]
- ]
+ ["PKCS8", "unenc-rsa-pkcs8.pem"],
+ ],
)
def test_unused_password(self, key_path, backend):
key_file = os.path.join("asymmetric", *key_path)
@@ -569,15 +597,33 @@ class TestPEMSerialization(object):
key_file,
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), password, backend
- )
+ ),
)
+ def test_invalid_encoding_with_traditional(self, backend):
+ key_file = os.path.join(
+ "asymmetric", "Traditional_OpenSSL_Serialization", "testrsa.pem"
+ )
+ key = load_vectors_from_file(
+ key_file,
+ lambda pemfile: load_pem_private_key(
+ pemfile.read(), None, backend
+ ),
+ mode="rb",
+ )
+
+ for enc in (Encoding.OpenSSH, Encoding.Raw, Encoding.X962):
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ enc, PrivateFormat.TraditionalOpenSSL, NoEncryption()
+ )
+
@pytest.mark.parametrize(
"key_path",
[
["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
- ["PKCS8", "enc-rsa-pkcs8.pem"]
- ]
+ ["PKCS8", "enc-rsa-pkcs8.pem"],
+ ],
)
def test_password_not_bytes(self, key_path, backend):
key_file = os.path.join("asymmetric", *key_path)
@@ -588,15 +634,15 @@ class TestPEMSerialization(object):
key_file,
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), password, backend
- )
+ ),
)
@pytest.mark.parametrize(
"key_path",
[
["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
- ["PKCS8", "enc-rsa-pkcs8.pem"]
- ]
+ ["PKCS8", "enc-rsa-pkcs8.pem"],
+ ],
)
def test_wrong_password(self, key_path, backend):
key_file = os.path.join("asymmetric", *key_path)
@@ -607,19 +653,18 @@ class TestPEMSerialization(object):
key_file,
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), password, backend
- )
+ ),
)
@pytest.mark.parametrize(
("key_path", "password"),
itertools.product(
[
- ["Traditional_OpenSSL_Serialization",
- "testrsa-encrypted.pem"],
+ ["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"],
["PKCS8", "enc-rsa-pkcs8.pem"],
],
- [b"", None]
- )
+ [b"", None],
+ ),
)
def test_missing_password(self, key_path, password, backend):
key_file = os.path.join("asymmetric", *key_path)
@@ -629,16 +674,14 @@ class TestPEMSerialization(object):
key_file,
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), password, backend
- )
+ ),
)
def test_wrong_private_format(self, backend):
key_data = b"---- NOT A KEY ----\n"
with pytest.raises(ValueError):
- load_pem_private_key(
- key_data, None, backend
- )
+ load_pem_private_key(key_data, None, backend)
with pytest.raises(ValueError):
load_pem_private_key(
@@ -659,7 +702,8 @@ class TestPEMSerialization(object):
def test_corrupt_traditional_format(self, backend):
# privkey.pem with a bunch of data missing.
- key_data = textwrap.dedent("""\
+ key_data = textwrap.dedent(
+ """\
-----BEGIN RSA PRIVATE KEY-----
MIIBPAIBAAJBAKrbeqkuRk8VcRmWFmtP+LviMB3+6dizWW3DwaffznyHGAFwUJ/I
Tv0XtbsCyl3QoyKGhrOAy3RvPK5M38iuXT0CAwEAAQJAZ3cnzaHXM/bxGaR5CR1R
@@ -668,12 +712,11 @@ class TestPEMSerialization(object):
rJBhdTe0v5pCeQIhAIZfkiGgGBX4cIuuckzEm43g9WMUjxP/0GlK39vIyihxAiEA
mymehFRT0MvqW5xAKAx7Pgkt8HVKwVhc2LwGKHE0DZM=
-----END RSA PRIVATE KEY-----
- """).encode()
+ """
+ ).encode()
with pytest.raises(ValueError):
- load_pem_private_key(
- key_data, None, backend
- )
+ load_pem_private_key(key_data, None, backend)
with pytest.raises(ValueError):
load_pem_private_key(
@@ -682,7 +725,8 @@ class TestPEMSerialization(object):
def test_traditional_encrypted_corrupt_format(self, backend):
# privkey.pem with a single bit flipped
- key_data = textwrap.dedent("""\
+ key_data = textwrap.dedent(
+ """\
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: <,ENCRYPTED
DEK-Info: AES-128-CBC,5E22A2BD85A653FB7A3ED20DE84F54CD
@@ -695,22 +739,20 @@ class TestPEMSerialization(object):
5A295jD9BQp9CY0nNFSsy+qiXWToq2xT3y5zVNEStmN0SCGNaIlUnJzL9IHW+oMI
kPmXZMnAYBWeeCF1gf3J3aE5lZInegHNfEI0+J0LazC2aNU5Dg/BNqrmRqKWEIo/
-----END RSA PRIVATE KEY-----
- """).encode()
+ """
+ ).encode()
password = b"this password is wrong"
with pytest.raises(ValueError):
- load_pem_private_key(
- key_data, None, backend
- )
+ load_pem_private_key(key_data, None, backend)
with pytest.raises(ValueError):
- load_pem_private_key(
- key_data, password, backend
- )
+ load_pem_private_key(key_data, password, backend)
def test_unsupported_key_encryption(self, backend):
- key_data = textwrap.dedent("""\
+ key_data = textwrap.dedent(
+ """\
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: FAKE-123,5E22A2BD85A653FB7A3ED20DE84F54CD
@@ -723,18 +765,18 @@ class TestPEMSerialization(object):
5A295jD9BQp9CY0nNFSsy+qiXWToq2xT3y5zVNEStmN0SCGNaIlUnJzL9IHW+oMI
kPmXZMnAYBWeeCF1gf3J3aE5lZInegHNfEI0+J0LazC2aNU5Dg/BNqrmRqKWEIo/
-----END RSA PRIVATE KEY-----
- """).encode()
+ """
+ ).encode()
password = b"password"
- with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
- load_pem_private_key(
- key_data, password, backend
- )
+ with pytest.raises(ValueError):
+ load_pem_private_key(key_data, password, backend)
def test_corrupt_pkcs8_format(self, backend):
# unenc-rsa-pkcs8.pem with a bunch of data missing.
- key_data = textwrap.dedent("""\
+ key_data = textwrap.dedent(
+ """\
-----BEGIN PRIVATE KEY-----
MIICdQIBADALBgkqhkiG9w0BAQEEggJhMIICXQIBAAKBgQC7JHoJfg6yNzLMOWet
8Z49a4KD0dCspMAYvo2YAMB7/wdEycocujbhJ2n/seONi+5XqTqqFkM5VBl8rmkk
@@ -750,12 +792,11 @@ class TestPEMSerialization(object):
Xxg/SNpjEIv+qAyUD96XVlOJlOIeLHQ8kYE0C6ZA+MsqYIzgAreJk88Yn0lU/X0/
mu/UpE/BRZmR
-----END PRIVATE KEY-----
- """).encode()
+ """
+ ).encode()
with pytest.raises(ValueError):
- load_pem_private_key(
- key_data, None, backend
- )
+ load_pem_private_key(key_data, None, backend)
with pytest.raises(ValueError):
load_pem_private_key(
@@ -764,7 +805,8 @@ class TestPEMSerialization(object):
def test_pks8_encrypted_corrupt_format(self, backend):
# enc-rsa-pkcs8.pem with some bits flipped.
- key_data = textwrap.dedent("""\
+ key_data = textwrap.dedent(
+ """\
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICojAcBgoqhkiG9w0BDAEDMA4ECHK0M0+QuEL9AgIBIcSCAoDRq+KRY+0XP0tO
lwBTzViiXSXoyNnKAZKt5r5K/fGNntv22g/1s/ZNCetrqsJDC5eMUPPacz06jFq/
@@ -782,27 +824,23 @@ class TestPEMSerialization(object):
6JLgl8FrvdfjHwIvmSOO1YMNmILBq000Q8WDqyErBDs4hsvtO6VQ4LeqJj6gClX3
qeJNaJFu
-----END ENCRYPTED PRIVATE KEY-----
- """).encode()
+ """
+ ).encode()
password = b"this password is wrong"
with pytest.raises(ValueError):
- load_pem_private_key(
- key_data, None, backend
- )
+ load_pem_private_key(key_data, None, backend)
with pytest.raises(ValueError):
- load_pem_private_key(
- key_data, password, backend
- )
+ load_pem_private_key(key_data, password, backend)
def test_rsa_pkcs8_encrypted_values(self, backend):
pkey = load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", "enc-rsa-pkcs8.pem"),
+ os.path.join("asymmetric", "PKCS8", "enc-rsa-pkcs8.pem"),
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), b"foobar", backend
- )
+ ),
)
assert pkey
@@ -813,7 +851,8 @@ class TestPEMSerialization(object):
"376a7fe5b19f95b35ca358ea5c8abd7ae051d49cd2f1e45969a1ae945460"
"3c14b278664a0e414ebc8913acb6203626985525e17a600611b028542dd0"
"562aad787fb4f1650aa318cdcff751e1b187cbf6785fbe164e9809491b95"
- "dd68480567c99b1a57", 16
+ "dd68480567c99b1a57",
+ 16,
)
assert numbers.public_numbers.e == 65537
@@ -823,37 +862,43 @@ class TestPEMSerialization(object):
"f3d9785c3a2c09e4c8090909fb3721e19a3009ec21221523a729265707a5"
"8f13063671c42a4096cad378ef2510cb59e23071489d8893ac4934dd149f"
"34f2d094bea57f1c8027c3a77248ac9b91218737d0c3c3dfa7d7829e6977"
- "cf7d995688c86c81", 16
+ "cf7d995688c86c81",
+ 16,
)
assert numbers.p == int(
"00db122ac857b2c0437d7616daa98e597bb75ca9ad3a47a70bec10c10036"
"03328794b225c8e3eee6ffd3fd6d2253d28e071fe27d629ab072faa14377"
- "ce6118cb67", 16
+ "ce6118cb67",
+ 16,
)
assert numbers.q == int(
"00df1b8aa8506fcbbbb9d00257f2975e38b33d2698fd0f37e82d7ef38c56"
"f21b6ced63c825383782a7115cfcc093300987dbd2853b518d1c8f26382a"
- "2d2586d391", 16
+ "2d2586d391",
+ 16,
)
assert numbers.dmp1 == int(
"00be18aca13e60712fdf5daa85421eb10d86d654b269e1255656194fb0c4"
"2dd01a1070ea12c19f5c39e09587af02f7b1a1030d016a9ffabf3b36d699"
- "ceaf38d9bf", 16
+ "ceaf38d9bf",
+ 16,
)
assert numbers.dmq1 == int(
"71aa8978f90a0c050744b77cf1263725b203ac9f730606d8ae1d289dce4a"
"28b8d534e9ea347aeb808c73107e583eb80c546d2bddadcdb3c82693a4c1"
- "3d863451", 16
+ "3d863451",
+ 16,
)
assert numbers.iqmp == int(
"136b7b1afac6e6279f71b24217b7083485a5e827d156024609dae39d48a6"
"bdb55af2f062cc4a3b077434e6fffad5faa29a2b5dba2bed3e4621e478c0"
- "97ccfe7f", 16
+ "97ccfe7f",
+ 16,
)
def test_load_pem_dsa_private_key(self, backend):
@@ -861,7 +906,7 @@ class TestPEMSerialization(object):
os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"),
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), None, backend
- )
+ ),
)
assert key
assert isinstance(key, dsa.DSAPrivateKey)
@@ -872,15 +917,14 @@ class TestPEMSerialization(object):
num = key.private_numbers()
pub = num.public_numbers
parameter_numbers = pub.parameter_numbers
- assert num.x == int("00a535a8e1d0d91beafc8bee1d9b2a3a8de3311203",
- 16)
+ assert num.x == int("00a535a8e1d0d91beafc8bee1d9b2a3a8de3311203", 16)
assert pub.y == int(
"2b260ea97dc6a12ae932c640e7df3d8ff04a8a05a0324f8d5f1b23f15fa1"
"70ff3f42061124eff2586cb11b49a82dcdc1b90fc6a84fb10109cb67db5d"
"2da971aeaf17be5e37284563e4c64d9e5fc8480258b319f0de29d54d8350"
"70d9e287914d77df81491f4423b62da984eb3f45eb2a29fcea5dae525ac6"
"ab6bcce04bfdf5b6",
- 16
+ 16,
)
assert parameter_numbers.p == int(
@@ -889,11 +933,12 @@ class TestPEMSerialization(object):
"071d4dceb2782794ad393cc08a4d4ada7f68d6e839a5fcd34b4e402d82cb"
"8a8cb40fec31911bf9bd360b034caacb4c5e947992573c9e90099c1b0f05"
"940cabe5d2de49a167",
- 16
+ 16,
)
assert parameter_numbers.q == int(
- "00adc0e869b36f0ac013a681fdf4d4899d69820451", 16)
+ "00adc0e869b36f0ac013a681fdf4d4899d69820451", 16
+ )
assert parameter_numbers.g == int(
"008c6b4589afa53a4d1048bfc346d1f386ca75521ccf72ddaa251286880e"
@@ -901,69 +946,61 @@ class TestPEMSerialization(object):
"e71141ba324f5b93131929182c88a9fa4062836066cebe74b5c6690c7d10"
"1106c240ab7ebd54e4e3301fd086ce6adac922fb2713a2b0887cba13b9bc"
"68ce5cfff241cd3246",
- 16
+ 16,
)
@pytest.mark.parametrize(
- ("key_file", "password"),
- [
- ("bad-oid-dsa-key.pem", None),
- ]
+ ("key_file", "password"), [("bad-oid-dsa-key.pem", None)]
)
def test_load_bad_oid_key(self, key_file, password, backend):
with pytest.raises(ValueError):
load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", key_file),
+ os.path.join("asymmetric", "PKCS8", key_file),
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), password, backend
- )
+ ),
)
@pytest.mark.parametrize(
- ("key_file", "password"),
- [
- ("bad-encryption-oid.pem", b"password"),
- ]
+ ("key_file", "password"), [("bad-encryption-oid.pem", b"password")]
)
def test_load_bad_encryption_oid_key(self, key_file, password, backend):
- with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
+ with pytest.raises(ValueError):
load_vectors_from_file(
- os.path.join(
- "asymmetric", "PKCS8", key_file),
+ os.path.join("asymmetric", "PKCS8", key_file),
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), password, backend
- )
+ ),
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
class TestRSASSHSerialization(object):
def test_load_ssh_public_key_unsupported(self, backend):
- ssh_key = b'ecdsa-sha2-junk AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY='
+ ssh_key = b"ecdsa-sha2-junk AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY="
with pytest.raises(UnsupportedAlgorithm):
load_ssh_public_key(ssh_key, backend)
def test_load_ssh_public_key_bad_format(self, backend):
- ssh_key = b'ssh-rsa not-a-real-key'
+ ssh_key = b"ssh-rsa not-a-real-key"
with pytest.raises(ValueError):
load_ssh_public_key(ssh_key, backend)
def test_load_ssh_public_key_rsa_too_short(self, backend):
- ssh_key = b'ssh-rsa'
+ ssh_key = b"ssh-rsa"
with pytest.raises(ValueError):
load_ssh_public_key(ssh_key, backend)
def test_load_ssh_public_key_truncated_int(self, backend):
- ssh_key = b'ssh-rsa AAAAB3NzaC1yc2EAAAA='
+ ssh_key = b"ssh-rsa AAAAB3NzaC1yc2EAAAA="
with pytest.raises(ValueError):
load_ssh_public_key(ssh_key, backend)
- ssh_key = b'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAACKr+IHXo'
+ ssh_key = b"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAACKr+IHXo"
with pytest.raises(ValueError):
load_ssh_public_key(ssh_key, backend)
@@ -1032,16 +1069,18 @@ class TestRSASSHSerialization(object):
expected_e = 0x10001
expected_n = int(
- '00C3BBF5D13F59322BA0A0B77EA0B6CF570241628AE24B5BA454D'
- '23DCA295652B3523B67752653DFFD69587FAD9578DD6406F23691'
- 'EA491C3F8B2D391D0312D9653C303B651067ADF887A5241843CEF'
- '8019680A088E092FEC305FB04EA070340BB9BD0F1635B2AD84142'
- '61B4E2D010ABD8FC6D2FB768912F78EE6B05A60857532B75B75EF'
- 'C007601A4EF58BA947B7E75E38F3443CDD87E7C138A1DAD9D9FB3'
- '19FF69DA43A9F6F6B0CD243F042CD1A5AFAEB286BD46AEB2D922B'
- 'D01385D6892167074A0907F94A2BF08A54ABB2FFFFC89920861D0'
- '46F8706AB88DDADBD9E8204D48B87789081E074024C8996783B31'
- '7076A98ABF0A2D8550EAF2097D8CCC7BE76EF', 16)
+ "00C3BBF5D13F59322BA0A0B77EA0B6CF570241628AE24B5BA454D"
+ "23DCA295652B3523B67752653DFFD69587FAD9578DD6406F23691"
+ "EA491C3F8B2D391D0312D9653C303B651067ADF887A5241843CEF"
+ "8019680A088E092FEC305FB04EA070340BB9BD0F1635B2AD84142"
+ "61B4E2D010ABD8FC6D2FB768912F78EE6B05A60857532B75B75EF"
+ "C007601A4EF58BA947B7E75E38F3443CDD87E7C138A1DAD9D9FB3"
+ "19FF69DA43A9F6F6B0CD243F042CD1A5AFAEB286BD46AEB2D922B"
+ "D01385D6892167074A0907F94A2BF08A54ABB2FFFFC89920861D0"
+ "46F8706AB88DDADBD9E8204D48B87789081E074024C8996783B31"
+ "7076A98ABF0A2D8550EAF2097D8CCC7BE76EF",
+ 16,
+ )
expected = rsa.RSAPublicNumbers(expected_e, expected_n)
@@ -1051,7 +1090,7 @@ class TestRSASSHSerialization(object):
@pytest.mark.requires_backend_interface(interface=DSABackend)
class TestDSSSSHSerialization(object):
def test_load_ssh_public_key_dss_too_short(self, backend):
- ssh_key = b'ssh-dss'
+ ssh_key = b"ssh-dss"
with pytest.raises(ValueError):
load_ssh_public_key(ssh_key, backend)
@@ -1134,14 +1173,16 @@ class TestDSSSSHSerialization(object):
"96a7032c01cdd8485b5cbfb73a46bb04708f98a18bc88d4c7812b284da8f900"
"6e473e89897f9bc9125c69bbfd8ef691c0e76c1c34e6c843b8fe240e6e5aeb3"
"13486e5fa917ab1288ff1a6ebcf9dcdeed3c5fc88474e30476f53a5ec816ef6"
- "9f4", 16
+ "9f4",
+ 16,
)
expected_p = int(
"b9b052d7f07630148d4d838b17790ef4f43437238ebebd5032ea483fd7b7902"
"5ec3dc65ebd563ab586a633b4344f6acd10af31353bcf29111fa5e3b8d5c1e8"
"7befe3c65f9b8be69c740716698c8366c8ef925b9cec1dcd69e73d926b554e2"
"b4b6ddd1453eab39ba0f846e1555adcc33c5a8637128c9ed61104a45505a748"
- "f6db", 16
+ "f6db",
+ 16,
)
expected_q = 1230879958723280233885494314531920096931919647917
expected_g = int(
@@ -1149,11 +1190,12 @@ class TestDSSSSHSerialization(object):
"7bc249b6cf8f5f5c5022afefd4df5bf9d13bbdf182df5af2a5c5d1dc7604185"
"7d5b0e4b22b856c300f850a3b00bac394b728755b8b7a56522eefc491573967"
"debb5982fc94d6a8c291f758feae63ad769a5621947221522a2dc31d18ede6f"
- "b656", 16
+ "b656",
+ 16,
)
expected = dsa.DSAPublicNumbers(
expected_y,
- dsa.DSAParameterNumbers(expected_p, expected_q, expected_g)
+ dsa.DSAParameterNumbers(expected_p, expected_q, expected_g),
)
assert numbers == expected
@@ -1174,17 +1216,32 @@ class TestECDSASSHSerialization(object):
expected_x = int(
"44196257377740326295529888716212621920056478823906609851236662550"
- "785814128027", 10
+ "785814128027",
+ 10,
)
expected_y = int(
"12257763433170736656417248739355923610241609728032203358057767672"
- "925775019611", 10
+ "925775019611",
+ 10,
)
assert key.public_numbers() == ec.EllipticCurvePublicNumbers(
expected_x, expected_y, ec.SECP256R1()
)
+ def test_load_ssh_public_key_byteslike(self, backend):
+ _skip_curve_unsupported(backend, ec.SECP256R1())
+
+ ssh_key = (
+ b"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAy"
+ b"NTYAAABBBGG2MfkHXp0UkxUyllDzWNBAImsvt5t7pFtTXegZK2WbGxml8zMrgWi5"
+ b"teIg1TO03/FD9hbpBFgBeix3NrCFPls= root@cloud-server-01"
+ )
+ assert load_ssh_public_key(bytearray(ssh_key), backend)
+ if six.PY3:
+ assert load_ssh_public_key(memoryview(ssh_key), backend)
+ assert load_ssh_public_key(memoryview(bytearray(ssh_key)), backend)
+
def test_load_ssh_public_key_ecdsa_nist_p384(self, backend):
_skip_curve_unsupported(backend, ec.SECP384R1())
ssh_key = (
@@ -1197,11 +1254,13 @@ class TestECDSASSHSerialization(object):
expected_x = int(
"31541830871345183397582554827482786756220448716666815789487537666"
- "592636882822352575507883817901562613492450642523901", 10
+ "592636882822352575507883817901562613492450642523901",
+ 10,
)
expected_y = int(
"15111413269431823234030344298767984698884955023183354737123929430"
- "995703524272335782455051101616329050844273733614670", 10
+ "995703524272335782455051101616329050844273733614670",
+ 10,
)
assert key.public_numbers() == ec.EllipticCurvePublicNumbers(
@@ -1222,12 +1281,14 @@ class TestECDSASSHSerialization(object):
expected_x = int(
"54124123120178189598842622575230904027376313369742467279346415219"
"77809037378785192537810367028427387173980786968395921877911964629"
- "142163122798974160187785455", 10
+ "142163122798974160187785455",
+ 10,
)
expected_y = int(
"16111775122845033200938694062381820957441843014849125660011303579"
"15284560361402515564433711416776946492019498546572162801954089916"
- "006665939539407104638103918", 10
+ "006665939539407104638103918",
+ 10,
)
assert key.public_numbers() == ec.EllipticCurvePublicNumbers(
@@ -1274,6 +1335,51 @@ class TestECDSASSHSerialization(object):
load_ssh_public_key(ssh_key, backend)
+@pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+)
+class TestEd25519SSHSerialization(object):
+ def test_load_ssh_public_key(self, backend):
+ ssh_key = (
+ b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2fgpmpYO61qeAxGd0wgRaN/E4"
+ b"GR+xWvBmvxjxrB1vG user@chiron.local"
+ )
+ key = load_ssh_public_key(ssh_key, backend)
+ assert isinstance(key, ed25519.Ed25519PublicKey)
+ assert key.public_bytes(Encoding.Raw, PublicFormat.Raw) == (
+ b"m\x9f\x82\x99\xa9`\xee\xb5\xa9\xe01\x19\xdd0\x81\x16\x8d\xfc"
+ b"N\x06G\xecV\xbc\x19\xaf\xc6<k\x07[\xc6"
+ )
+
+ def test_public_bytes_openssh(self, backend):
+ ssh_key = (
+ b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2fgpmpYO61qeAxGd0wgRaN/E4"
+ b"GR+xWvBmvxjxrB1vG"
+ )
+ key = load_ssh_public_key(ssh_key, backend)
+ assert isinstance(key, ed25519.Ed25519PublicKey)
+ assert (
+ key.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH) == ssh_key
+ )
+
+ def test_load_ssh_public_key_not_32_bytes(self, backend):
+ ssh_key = (
+ b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI22fgpmpYO61qeAxGd0wgRaN/E4"
+ b"GR+xWvBmvxjxrB1vGaGVs user@chiron.local"
+ )
+ with pytest.raises(ValueError):
+ load_ssh_public_key(ssh_key, backend)
+
+ def test_load_ssh_public_key_trailing_data(self, backend):
+ ssh_key = (
+ b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2fgpmpYO61qeAxGd0wgRa"
+ b"N/E4GR+xWvBmvxjxrB1vGdHJhaWxpbmdkYXRh user@chiron.local"
+ )
+ with pytest.raises(ValueError):
+ load_ssh_public_key(ssh_key, backend)
+
+
class TestKeySerializationEncryptionTypes(object):
def test_non_bytes_password(self):
with pytest.raises(ValueError):
@@ -1285,128 +1391,959 @@ class TestKeySerializationEncryptionTypes(object):
@pytest.mark.supported(
- only_if=lambda backend: backend.x448_supported(),
- skip_message="Requires OpenSSL with X448 support"
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
)
-class TestX448Serialization(object):
+class TestEd25519Serialization(object):
def test_load_der_private_key(self, backend):
data = load_vectors_from_file(
- os.path.join("asymmetric", "X448", "x448-pkcs8-enc.der"),
+ os.path.join("asymmetric", "Ed25519", "ed25519-pkcs8-enc.der"),
lambda derfile: derfile.read(),
- mode="rb"
+ mode="rb",
)
unencrypted = load_vectors_from_file(
- os.path.join("asymmetric", "X448", "x448-pkcs8.der"),
+ os.path.join("asymmetric", "Ed25519", "ed25519-pkcs8.der"),
lambda derfile: derfile.read(),
- mode="rb"
+ mode="rb",
)
key = load_der_private_key(data, b"password", backend)
- assert key.private_bytes(
- Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
- ) == unencrypted
+ assert (
+ key.private_bytes(
+ Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
+ )
+ == unencrypted
+ )
def test_load_pem_private_key(self, backend):
data = load_vectors_from_file(
- os.path.join("asymmetric", "X448", "x448-pkcs8-enc.pem"),
+ os.path.join("asymmetric", "Ed25519", "ed25519-pkcs8-enc.pem"),
lambda pemfile: pemfile.read(),
- mode="rb"
+ mode="rb",
)
unencrypted = load_vectors_from_file(
- os.path.join("asymmetric", "X448", "x448-pkcs8.pem"),
+ os.path.join("asymmetric", "Ed25519", "ed25519-pkcs8.pem"),
lambda pemfile: pemfile.read(),
- mode="rb"
+ mode="rb",
)
key = load_pem_private_key(data, b"password", backend)
- assert key.private_bytes(
- Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
- ) == unencrypted
+ assert (
+ key.private_bytes(
+ Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
+ )
+ == unencrypted
+ )
@pytest.mark.parametrize(
("key_path", "encoding", "loader"),
[
(
- ["X448", "x448-pub.pem"],
+ ["Ed25519", "ed25519-pub.pem"],
Encoding.PEM,
- load_pem_public_key
+ load_pem_public_key,
),
(
- ["X448", "x448-pub.der"],
+ ["Ed25519", "ed25519-pub.der"],
Encoding.DER,
- load_der_public_key
+ load_der_public_key,
),
- ]
+ ],
)
def test_load_public_key(self, key_path, encoding, loader, backend):
data = load_vectors_from_file(
os.path.join("asymmetric", *key_path),
lambda pemfile: pemfile.read(),
- mode="rb"
+ mode="rb",
)
public_key = loader(data, backend)
- assert public_key.public_bytes(
- encoding, PublicFormat.SubjectPublicKeyInfo
- ) == data
+ assert (
+ public_key.public_bytes(
+ encoding, PublicFormat.SubjectPublicKeyInfo
+ )
+ == data
+ )
+
+ def test_openssl_serialization_unsupported(self, backend):
+ key = ed25519.Ed25519PrivateKey.generate()
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.PEM,
+ PrivateFormat.TraditionalOpenSSL,
+ NoEncryption(),
+ )
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.DER,
+ PrivateFormat.TraditionalOpenSSL,
+ NoEncryption(),
+ )
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.x448_supported(),
+ skip_message="Requires OpenSSL with X448 support",
+)
+class TestX448Serialization(object):
+ def test_load_der_private_key(self, backend):
+ data = load_vectors_from_file(
+ os.path.join("asymmetric", "X448", "x448-pkcs8-enc.der"),
+ lambda derfile: derfile.read(),
+ mode="rb",
+ )
+ unencrypted = load_vectors_from_file(
+ os.path.join("asymmetric", "X448", "x448-pkcs8.der"),
+ lambda derfile: derfile.read(),
+ mode="rb",
+ )
+ key = load_der_private_key(data, b"password", backend)
+ assert (
+ key.private_bytes(
+ Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
+ )
+ == unencrypted
+ )
+
+ def test_load_pem_private_key(self, backend):
+ data = load_vectors_from_file(
+ os.path.join("asymmetric", "X448", "x448-pkcs8-enc.pem"),
+ lambda pemfile: pemfile.read(),
+ mode="rb",
+ )
+ unencrypted = load_vectors_from_file(
+ os.path.join("asymmetric", "X448", "x448-pkcs8.pem"),
+ lambda pemfile: pemfile.read(),
+ mode="rb",
+ )
+ key = load_pem_private_key(data, b"password", backend)
+ assert (
+ key.private_bytes(
+ Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
+ )
+ == unencrypted
+ )
+
+ @pytest.mark.parametrize(
+ ("key_path", "encoding", "loader"),
+ [
+ (["X448", "x448-pub.pem"], Encoding.PEM, load_pem_public_key),
+ (["X448", "x448-pub.der"], Encoding.DER, load_der_public_key),
+ ],
+ )
+ def test_load_public_key(self, key_path, encoding, loader, backend):
+ data = load_vectors_from_file(
+ os.path.join("asymmetric", *key_path),
+ lambda pemfile: pemfile.read(),
+ mode="rb",
+ )
+ public_key = loader(data, backend)
+ assert (
+ public_key.public_bytes(
+ encoding, PublicFormat.SubjectPublicKeyInfo
+ )
+ == data
+ )
+
+ def test_openssl_serialization_unsupported(self, backend):
+ key = x448.X448PrivateKey.generate()
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.PEM,
+ PrivateFormat.TraditionalOpenSSL,
+ NoEncryption(),
+ )
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.DER,
+ PrivateFormat.TraditionalOpenSSL,
+ NoEncryption(),
+ )
+
+ def test_openssh_serialization_unsupported(self, backend):
+ key = x448.X448PrivateKey.generate()
+ with pytest.raises(ValueError):
+ key.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+ )
@pytest.mark.supported(
only_if=lambda backend: backend.x25519_supported(),
- skip_message="Requires OpenSSL with X25519 support"
+ skip_message="Requires OpenSSL with X25519 support",
)
class TestX25519Serialization(object):
def test_load_der_private_key(self, backend):
data = load_vectors_from_file(
os.path.join("asymmetric", "X25519", "x25519-pkcs8-enc.der"),
lambda derfile: derfile.read(),
- mode="rb"
+ mode="rb",
)
unencrypted = load_vectors_from_file(
os.path.join("asymmetric", "X25519", "x25519-pkcs8.der"),
lambda derfile: derfile.read(),
- mode="rb"
+ mode="rb",
)
key = load_der_private_key(data, b"password", backend)
- assert key.private_bytes(
- Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
- ) == unencrypted
+ assert (
+ key.private_bytes(
+ Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
+ )
+ == unencrypted
+ )
def test_load_pem_private_key(self, backend):
data = load_vectors_from_file(
os.path.join("asymmetric", "X25519", "x25519-pkcs8-enc.pem"),
lambda pemfile: pemfile.read(),
- mode="rb"
+ mode="rb",
)
unencrypted = load_vectors_from_file(
os.path.join("asymmetric", "X25519", "x25519-pkcs8.pem"),
lambda pemfile: pemfile.read(),
- mode="rb"
+ mode="rb",
)
key = load_pem_private_key(data, b"password", backend)
- assert key.private_bytes(
- Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
- ) == unencrypted
+ assert (
+ key.private_bytes(
+ Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
+ )
+ == unencrypted
+ )
@pytest.mark.parametrize(
("key_path", "encoding", "loader"),
[
- (
- ["X25519", "x25519-pub.pem"],
+ (["X25519", "x25519-pub.pem"], Encoding.PEM, load_pem_public_key),
+ (["X25519", "x25519-pub.der"], Encoding.DER, load_der_public_key),
+ ],
+ )
+ def test_load_public_key(self, key_path, encoding, loader, backend):
+ data = load_vectors_from_file(
+ os.path.join("asymmetric", *key_path),
+ lambda pemfile: pemfile.read(),
+ mode="rb",
+ )
+ public_key = loader(data, backend)
+ assert (
+ public_key.public_bytes(
+ encoding, PublicFormat.SubjectPublicKeyInfo
+ )
+ == data
+ )
+
+ def test_openssl_serialization_unsupported(self, backend):
+ key = x25519.X25519PrivateKey.generate()
+ with pytest.raises(ValueError):
+ key.private_bytes(
Encoding.PEM,
- load_pem_public_key
- ),
- (
- ["X25519", "x25519-pub.der"],
+ PrivateFormat.TraditionalOpenSSL,
+ NoEncryption(),
+ )
+ with pytest.raises(ValueError):
+ key.private_bytes(
Encoding.DER,
- load_der_public_key
- ),
- ]
+ PrivateFormat.TraditionalOpenSSL,
+ NoEncryption(),
+ )
+
+ def test_openssh_serialization_unsupported(self, backend):
+ key = x25519.X25519PrivateKey.generate()
+ with pytest.raises(ValueError):
+ key.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+ )
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+)
+class TestEd448Serialization(object):
+ def test_load_der_private_key(self, backend):
+ data = load_vectors_from_file(
+ os.path.join("asymmetric", "Ed448", "ed448-pkcs8-enc.der"),
+ lambda derfile: derfile.read(),
+ mode="rb",
+ )
+ unencrypted = load_vectors_from_file(
+ os.path.join("asymmetric", "Ed448", "ed448-pkcs8.der"),
+ lambda derfile: derfile.read(),
+ mode="rb",
+ )
+ key = load_der_private_key(data, b"password", backend)
+ assert (
+ key.private_bytes(
+ Encoding.DER, PrivateFormat.PKCS8, NoEncryption()
+ )
+ == unencrypted
+ )
+
+ def test_load_pem_private_key(self, backend):
+ data = load_vectors_from_file(
+ os.path.join("asymmetric", "Ed448", "ed448-pkcs8-enc.pem"),
+ lambda pemfile: pemfile.read(),
+ mode="rb",
+ )
+ unencrypted = load_vectors_from_file(
+ os.path.join("asymmetric", "Ed448", "ed448-pkcs8.pem"),
+ lambda pemfile: pemfile.read(),
+ mode="rb",
+ )
+ key = load_pem_private_key(data, b"password", backend)
+ assert (
+ key.private_bytes(
+ Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()
+ )
+ == unencrypted
+ )
+
+ @pytest.mark.parametrize(
+ ("key_path", "encoding", "loader"),
+ [
+ (["Ed448", "ed448-pub.pem"], Encoding.PEM, load_pem_public_key),
+ (["Ed448", "ed448-pub.der"], Encoding.DER, load_der_public_key),
+ ],
)
def test_load_public_key(self, key_path, encoding, loader, backend):
data = load_vectors_from_file(
os.path.join("asymmetric", *key_path),
lambda pemfile: pemfile.read(),
- mode="rb"
+ mode="rb",
)
public_key = loader(data, backend)
- assert public_key.public_bytes(
- encoding, PublicFormat.SubjectPublicKeyInfo
- ) == data
+ assert (
+ public_key.public_bytes(
+ encoding, PublicFormat.SubjectPublicKeyInfo
+ )
+ == data
+ )
+
+ def test_openssl_serialization_unsupported(self, backend):
+ key = ed448.Ed448PrivateKey.generate()
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.PEM,
+ PrivateFormat.TraditionalOpenSSL,
+ NoEncryption(),
+ )
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.DER,
+ PrivateFormat.TraditionalOpenSSL,
+ NoEncryption(),
+ )
+
+ def test_openssh_serialization_unsupported(self, backend):
+ key = ed448.Ed448PrivateKey.generate()
+ with pytest.raises(ValueError):
+ key.public_key().public_bytes(
+ Encoding.OpenSSH,
+ PublicFormat.OpenSSH,
+ )
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.PEM,
+ PrivateFormat.OpenSSH,
+ NoEncryption(),
+ )
+
+
+class TestDHSerialization(object):
+ """Test all options with least-supported key type."""
+
+ @pytest.mark.skip_fips(reason="non-FIPS parameters")
+ def test_dh_public_key(self, backend):
+ data = load_vectors_from_file(
+ os.path.join("asymmetric", "DH", "dhkey.pem"),
+ lambda pemfile: pemfile.read(),
+ mode="rb",
+ )
+ public_key = load_pem_private_key(data, None, backend).public_key()
+ for enc in (
+ Encoding.PEM,
+ Encoding.DER,
+ Encoding.OpenSSH,
+ Encoding.Raw,
+ Encoding.X962,
+ ):
+ for fmt in (
+ PublicFormat.SubjectPublicKeyInfo,
+ PublicFormat.PKCS1,
+ PublicFormat.OpenSSH,
+ PublicFormat.Raw,
+ PublicFormat.CompressedPoint,
+ PublicFormat.UncompressedPoint,
+ ):
+ if (
+ enc in (Encoding.PEM, Encoding.DER)
+ and fmt == PublicFormat.SubjectPublicKeyInfo
+ ):
+ # tested elsewhere
+ continue
+ with pytest.raises(ValueError):
+ public_key.public_bytes(enc, fmt)
+
+ @pytest.mark.skip_fips(reason="non-FIPS parameters")
+ def test_dh_private_key(self, backend):
+ data = load_vectors_from_file(
+ os.path.join("asymmetric", "DH", "dhkey.pem"),
+ lambda pemfile: pemfile.read(),
+ mode="rb",
+ )
+ private_key = load_pem_private_key(data, None, backend)
+ for enc in (
+ Encoding.PEM,
+ Encoding.DER,
+ Encoding.OpenSSH,
+ Encoding.Raw,
+ Encoding.X962,
+ ):
+ for fmt in (
+ PrivateFormat.PKCS8,
+ PrivateFormat.TraditionalOpenSSL,
+ PrivateFormat.Raw,
+ ):
+ if (
+ enc in (Encoding.PEM, Encoding.DER)
+ and fmt is PrivateFormat.PKCS8
+ ):
+ # tested elsewhere
+ continue
+ with pytest.raises(ValueError):
+ private_key.private_bytes(enc, fmt, NoEncryption())
+
+
+@pytest.mark.requires_backend_interface(interface=RSABackend)
+@pytest.mark.requires_backend_interface(interface=DSABackend)
+@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
+class TestOpenSSHSerialization(object):
+ @pytest.mark.parametrize(
+ ("key_file", "cert_file"),
+ [
+ ("rsa-psw.key.pub", None),
+ ("rsa-nopsw.key.pub", "rsa-nopsw.key-cert.pub"),
+ ("dsa-psw.key.pub", None),
+ ("dsa-nopsw.key.pub", "dsa-nopsw.key-cert.pub"),
+ ("ecdsa-psw.key.pub", None),
+ ("ecdsa-nopsw.key.pub", "ecdsa-nopsw.key-cert.pub"),
+ ("ed25519-psw.key.pub", None),
+ ("ed25519-nopsw.key.pub", "ed25519-nopsw.key-cert.pub"),
+ ],
+ )
+ def test_load_ssh_public_key(self, key_file, cert_file, backend):
+ if "ed25519" in key_file and not backend.ed25519_supported():
+ pytest.skip("Requires OpenSSL with Ed25519 support")
+
+ # normal public key
+ pub_data = load_vectors_from_file(
+ os.path.join("asymmetric", "OpenSSH", key_file),
+ lambda f: f.read(),
+ mode="rb",
+ )
+ public_key = load_ssh_public_key(pub_data, backend)
+ nocomment_data = b" ".join(pub_data.split()[:2])
+ assert (
+ public_key.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH)
+ == nocomment_data
+ )
+
+ self.run_partial_pubkey(pub_data, backend)
+
+ # parse public key with ssh certificate
+ if cert_file:
+ cert_data = load_vectors_from_file(
+ os.path.join("asymmetric", "OpenSSH", cert_file),
+ lambda f: f.read(),
+ mode="rb",
+ )
+ cert_key = load_ssh_public_key(cert_data, backend)
+ assert (
+ cert_key.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH)
+ == nocomment_data
+ )
+
+ # try with more spaces
+ cert_data = b" \t ".join(cert_data.split())
+ cert_key = load_ssh_public_key(cert_data, backend)
+ assert (
+ cert_key.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH)
+ == nocomment_data
+ )
+
+ self.run_partial_pubkey(cert_data, backend)
+
+ def run_partial_pubkey(self, pubdata, backend):
+ parts = pubdata.split()
+ raw = base64.b64decode(parts[1])
+ for i in range(1, len(raw)):
+ frag = base64.b64encode(raw[:i])
+ new_pub = b" ".join([parts[0], frag])
+ with pytest.raises(ValueError):
+ load_ssh_public_key(new_pub, backend)
+
+ @pytest.mark.parametrize(
+ ("key_file",),
+ [
+ ("rsa-nopsw.key",),
+ ("rsa-psw.key",),
+ ("dsa-nopsw.key",),
+ ("dsa-psw.key",),
+ ("ecdsa-nopsw.key",),
+ ("ecdsa-psw.key",),
+ ("ed25519-nopsw.key",),
+ ("ed25519-psw.key",),
+ ],
+ )
+ def test_load_ssh_private_key(self, key_file, backend):
+ if "ed25519" in key_file and not backend.ed25519_supported():
+ pytest.skip("Requires OpenSSL with Ed25519 support")
+ if "-psw" in key_file and not ssh._bcrypt_supported:
+ pytest.skip("Requires bcrypt module")
+
+ # read public and private key from ssh-keygen
+ priv_data = load_vectors_from_file(
+ os.path.join("asymmetric", "OpenSSH", key_file),
+ lambda f: f.read(),
+ mode="rb",
+ )
+ pub_data = load_vectors_from_file(
+ os.path.join("asymmetric", "OpenSSH", key_file + ".pub"),
+ lambda f: f.read(),
+ mode="rb",
+ )
+ nocomment_data = b" ".join(pub_data.split()[:2])
+
+ # load and compare
+ password = None
+ if "-psw" in key_file:
+ password = b"password"
+ private_key = load_ssh_private_key(priv_data, password, backend)
+ assert (
+ private_key.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ == nocomment_data
+ )
+
+ # bytearray
+ private_key = load_ssh_private_key(
+ bytearray(priv_data), password, backend
+ )
+ assert (
+ private_key.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ == nocomment_data
+ )
+
+ if six.PY3:
+ # memoryview(bytes)
+ private_key = load_ssh_private_key(
+ memoryview(priv_data), password, backend
+ )
+ assert (
+ private_key.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ == nocomment_data
+ )
+
+ # memoryview(bytearray)
+ private_key = load_ssh_private_key(
+ memoryview(bytearray(priv_data)), password, backend
+ )
+ assert (
+ private_key.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ == nocomment_data
+ )
+
+ # serialize with own code and reload
+ encryption = NoEncryption()
+ if password:
+ encryption = BestAvailableEncryption(password)
+ priv_data2 = private_key.private_bytes(
+ Encoding.PEM,
+ PrivateFormat.OpenSSH,
+ encryption,
+ )
+ private_key2 = load_ssh_private_key(priv_data2, password, backend)
+ assert (
+ private_key2.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ == nocomment_data
+ )
+
+ # make sure multi-line base64 is used
+ maxline = max(map(len, priv_data2.split(b"\n")))
+ assert maxline < 80
+
+ @pytest.mark.supported(
+ only_if=lambda backend: ssh._bcrypt_supported,
+ skip_message="Requires that bcrypt exists",
+ )
+ def test_bcrypt_encryption(self, backend):
+ private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+ pub1 = private_key.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+
+ for psw in (
+ b"1",
+ b"1234",
+ b"1234" * 4,
+ b"x" * 72,
+ ):
+ # BestAvailableEncryption does not handle bytes-like?
+ best = BestAvailableEncryption(psw)
+ encdata = private_key.private_bytes(
+ Encoding.PEM, PrivateFormat.OpenSSH, best
+ )
+ decoded_key = load_ssh_private_key(encdata, psw, backend)
+ pub2 = decoded_key.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ assert pub1 == pub2
+
+ # bytearray
+ decoded_key2 = load_ssh_private_key(
+ bytearray(encdata), psw, backend
+ )
+ pub2 = decoded_key2.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ assert pub1 == pub2
+
+ if six.PY3:
+ # memoryview(bytes)
+ decoded_key2 = load_ssh_private_key(
+ memoryview(encdata), psw, backend
+ )
+ pub2 = decoded_key2.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ assert pub1 == pub2
+
+ # memoryview(bytearray)
+ decoded_key2 = load_ssh_private_key(
+ memoryview(bytearray(encdata)), psw, backend
+ )
+ pub2 = decoded_key2.public_key().public_bytes(
+ Encoding.OpenSSH, PublicFormat.OpenSSH
+ )
+ assert pub1 == pub2
+
+ with pytest.raises(ValueError):
+ decoded_key = load_ssh_private_key(encdata, None, backend)
+ with pytest.raises(ValueError):
+ decoded_key = load_ssh_private_key(encdata, b"wrong", backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: not ssh._bcrypt_supported,
+ skip_message="Requires that bcrypt is missing",
+ )
+ def test_missing_bcrypt(self, backend):
+ priv_data = load_vectors_from_file(
+ os.path.join("asymmetric", "OpenSSH", "ecdsa-psw.key"),
+ lambda f: f.read(),
+ mode="rb",
+ )
+ with pytest.raises(UnsupportedAlgorithm):
+ load_ssh_private_key(priv_data, b"password", backend)
+
+ private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+ with pytest.raises(UnsupportedAlgorithm):
+ private_key.private_bytes(
+ Encoding.PEM,
+ PrivateFormat.OpenSSH,
+ BestAvailableEncryption(b"x"),
+ )
+
+ def test_fraglist_corners(self):
+ f = ssh._FragList()
+ with pytest.raises(ValueError):
+ f.put_mpint(-1)
+ f.put_mpint(0)
+ f.put_mpint(0x80)
+ assert f.tobytes() == b"\0\0\0\0" + b"\0\0\0\x02" + b"\0\x80"
+
+ def make_file(
+ self,
+ magic=b"openssh-key-v1\0",
+ ciphername=b"none",
+ kdfname=b"none",
+ kdfoptions=b"",
+ nkeys=1,
+ pub_type=b"ecdsa-sha2-nistp256",
+ pub_fields=(
+ b"nistp256",
+ b"\x04" * 65,
+ ),
+ priv_type=None,
+ priv_fields=(b"nistp256", b"\x04" * 65, b"\x7F" * 32),
+ comment=b"comment",
+ checkval1=b"1234",
+ checkval2=b"1234",
+ pad=None,
+ header=b"-----BEGIN OPENSSH PRIVATE KEY-----\n",
+ footer=b"-----END OPENSSH PRIVATE KEY-----\n",
+ cut=8192,
+ ):
+ """Create private key file"""
+ if not priv_type:
+ priv_type = pub_type
+
+ pub = ssh._FragList()
+ for elem in (pub_type,) + pub_fields:
+ pub.put_sshstr(elem)
+
+ secret = ssh._FragList([checkval1, checkval2])
+ for i in range(nkeys):
+ for elem in (priv_type,) + priv_fields + (comment,):
+ secret.put_sshstr(elem)
+
+ if pad is None:
+ pad_len = 8 - (secret.size() % 8)
+ pad = bytearray(range(1, 1 + pad_len))
+ secret.put_raw(pad)
+
+ main = ssh._FragList([magic])
+ main.put_sshstr(ciphername)
+ main.put_sshstr(kdfname)
+ main.put_sshstr(kdfoptions)
+ main.put_u32(nkeys)
+ for i in range(nkeys):
+ main.put_sshstr(pub)
+ main.put_sshstr(secret)
+
+ res = main.tobytes()
+ return ssh._ssh_pem_encode(res[:cut], header, footer)
+
+ def test_ssh_make_file(self, backend):
+ # check if works by default
+ data = self.make_file()
+ key = load_ssh_private_key(data, None, backend)
+ assert isinstance(key, ec.EllipticCurvePrivateKey)
+
+ def test_load_ssh_private_key_errors(self, backend):
+ # bad kdf
+ data = self.make_file(kdfname=b"unknown", ciphername=b"aes256-ctr")
+ with pytest.raises(UnsupportedAlgorithm):
+ load_ssh_private_key(data, None, backend)
+
+ # bad cipher
+ data = self.make_file(ciphername=b"unknown", kdfname=b"bcrypt")
+ with pytest.raises(UnsupportedAlgorithm):
+ load_ssh_private_key(data, None, backend)
+
+ # bad magic
+ data = self.make_file(magic=b"unknown")
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ # too few keys
+ data = self.make_file(nkeys=0)
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ # too many keys
+ data = self.make_file(nkeys=2)
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ def test_ssh_errors_bad_values(self, backend):
+ # bad curve
+ data = self.make_file(pub_type=b"ecdsa-sha2-nistp444")
+ with pytest.raises(UnsupportedAlgorithm):
+ load_ssh_private_key(data, None, backend)
+
+ # curve mismatch
+ data = self.make_file(priv_type=b"ecdsa-sha2-nistp384")
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ # invalid bigint
+ data = self.make_file(
+ priv_fields=(b"nistp256", b"\x04" * 65, b"\x80" * 32)
+ )
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ def test_ssh_errors_pubpriv_mismatch(self, backend):
+ # ecdsa public-private mismatch
+ data = self.make_file(
+ pub_fields=(
+ b"nistp256",
+ b"\x04" + b"\x05" * 64,
+ )
+ )
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ # rsa public-private mismatch
+ data = self.make_file(
+ pub_type=b"ssh-rsa",
+ pub_fields=(b"x" * 32,) * 2,
+ priv_fields=(b"z" * 32,) * 6,
+ )
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ # dsa public-private mismatch
+ data = self.make_file(
+ pub_type=b"ssh-dss",
+ pub_fields=(b"x" * 32,) * 4,
+ priv_fields=(b"z" * 32,) * 5,
+ )
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ # ed25519 public-private mismatch
+ sk = b"x" * 32
+ pk1 = b"y" * 32
+ pk2 = b"z" * 32
+ data = self.make_file(
+ pub_type=b"ssh-ed25519",
+ pub_fields=(pk1,),
+ priv_fields=(
+ pk1,
+ sk + pk2,
+ ),
+ )
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+ data = self.make_file(
+ pub_type=b"ssh-ed25519",
+ pub_fields=(pk1,),
+ priv_fields=(
+ pk2,
+ sk + pk1,
+ ),
+ )
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ def test_ssh_errors_bad_wrapper(self, backend):
+ # wrong header
+ data = self.make_file(header=b"-----BEGIN RSA PRIVATE KEY-----\n")
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ # wring footer
+ data = self.make_file(footer=b"-----END RSA PRIVATE KEY-----\n")
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ def test_ssh_no_padding(self, backend):
+ # no padding must work, if data is on block boundary
+ data = self.make_file(pad=b"", comment=b"")
+ key = load_ssh_private_key(data, None, backend)
+ assert isinstance(key, ec.EllipticCurvePrivateKey)
+
+ # no padding with right last byte
+ data = self.make_file(pad=b"", comment=b"\x08" * 8)
+ key = load_ssh_private_key(data, None, backend)
+ assert isinstance(key, ec.EllipticCurvePrivateKey)
+
+ # avoid unexpected padding removal
+ data = self.make_file(pad=b"", comment=b"1234\x01\x02\x03\x04")
+ key = load_ssh_private_key(data, None, backend)
+ assert isinstance(key, ec.EllipticCurvePrivateKey)
+
+ # bad padding with right size
+ data = self.make_file(pad=b"\x08" * 8, comment=b"")
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ def test_ssh_errors_bad_secrets(self, backend):
+ # checkval mismatch
+ data = self.make_file(checkval2=b"4321")
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ # bad padding, correct=1
+ data = self.make_file(pad=b"\x01\x02")
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+ data = self.make_file(pad=b"")
+ with pytest.raises(ValueError):
+ load_ssh_private_key(data, None, backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.elliptic_curve_supported(
+ ec.SECP192R1()
+ ),
+ skip_message="Requires backend support for ec.SECP192R1",
+ )
+ def test_serialize_ssh_private_key_errors_bad_curve(self, backend):
+ private_key = ec.generate_private_key(ec.SECP192R1(), backend)
+ with pytest.raises(ValueError):
+ private_key.private_bytes(
+ Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+ )
+
+ def test_serialize_ssh_private_key_errors(self, backend):
+ # bad encoding
+ private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+ with pytest.raises(ValueError):
+ private_key.private_bytes(
+ Encoding.DER, PrivateFormat.OpenSSH, NoEncryption()
+ )
+
+ # bad object type
+ with pytest.raises(ValueError):
+ ssh.serialize_ssh_private_key(object(), None)
+
+ private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+
+ # too long password
+ with pytest.raises(ValueError):
+ private_key.private_bytes(
+ Encoding.PEM,
+ PrivateFormat.OpenSSH,
+ BestAvailableEncryption(b"p" * 73),
+ )
+
+ # unknown encryption class
+ with pytest.raises(ValueError):
+ private_key.private_bytes(
+ Encoding.PEM,
+ PrivateFormat.OpenSSH,
+ DummyKeySerializationEncryption(),
+ )
+
+ @pytest.mark.parametrize(
+ ("key_path", "supported"),
+ [
+ (["Traditional_OpenSSL_Serialization", "dsa.1024.pem"], True),
+ (["Traditional_OpenSSL_Serialization", "dsa.2048.pem"], False),
+ (["Traditional_OpenSSL_Serialization", "dsa.3072.pem"], False),
+ ],
+ )
+ def test_dsa_private_key_sizes(self, key_path, supported, backend):
+ key = load_vectors_from_file(
+ os.path.join("asymmetric", *key_path),
+ lambda pemfile: load_pem_private_key(
+ pemfile.read(), None, backend
+ ),
+ mode="rb",
+ )
+ assert isinstance(key, dsa.DSAPrivateKey)
+ if supported:
+ res = key.private_bytes(
+ Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+ )
+ assert isinstance(res, bytes)
+ else:
+ with pytest.raises(ValueError):
+ key.private_bytes(
+ Encoding.PEM, PrivateFormat.OpenSSH, NoEncryption()
+ )
diff --git a/tests/hazmat/primitives/test_x25519.py b/tests/hazmat/primitives/test_x25519.py
index 17a911548..fd1137d9d 100644
--- a/tests/hazmat/primitives/test_x25519.py
+++ b/tests/hazmat/primitives/test_x25519.py
@@ -9,24 +9,24 @@ import os
import pytest
-from cryptography import utils
from cryptography.exceptions import _Reasons
-from cryptography.hazmat.backends.interfaces import DHBackend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.x25519 import (
- X25519PrivateKey, X25519PublicKey
+ X25519PrivateKey,
+ X25519PublicKey,
)
from ...utils import (
- load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
@pytest.mark.supported(
only_if=lambda backend: not backend.x25519_supported(),
- skip_message="Requires OpenSSL without X25519 support"
+ skip_message="Requires OpenSSL without X25519 support",
)
-@pytest.mark.requires_backend_interface(interface=DHBackend)
def test_x25519_unsupported(backend):
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM):
X25519PublicKey.from_public_bytes(b"0" * 32)
@@ -40,16 +40,15 @@ def test_x25519_unsupported(backend):
@pytest.mark.supported(
only_if=lambda backend: backend.x25519_supported(),
- skip_message="Requires OpenSSL with X25519 support"
+ skip_message="Requires OpenSSL with X25519 support",
)
-@pytest.mark.requires_backend_interface(interface=DHBackend)
class TestX25519Exchange(object):
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
os.path.join("asymmetric", "X25519", "rfc7748.txt"),
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_rfc7748(self, vector, backend):
private = binascii.unhexlify(vector["input_scalar"])
@@ -91,23 +90,16 @@ class TestX25519Exchange(object):
private = binascii.unhexlify(
"78f1e8edf14481b389448dac8f59c70b038e7cf92ef2c7eff57a72466e115296"
)
- private_key = X25519PrivateKey.from_private_bytes(
- private
- )
+ private_key = X25519PrivateKey.from_private_bytes(private)
public_key = X25519PublicKey.from_public_bytes(public)
with pytest.raises(ValueError):
private_key.exchange(public_key)
- def test_deprecated_public_bytes(self, backend):
- key = X25519PrivateKey.generate().public_key()
- with pytest.warns(utils.DeprecatedIn25):
- key.public_bytes()
-
def test_public_bytes_bad_args(self, backend):
key = X25519PrivateKey.generate().public_key()
with pytest.raises(ValueError):
key.public_bytes(None, serialization.PublicFormat.Raw)
- with pytest.raises(ValueError):
+ with pytest.raises(TypeError):
key.public_bytes(serialization.Encoding.Raw)
# These vectors are also from RFC 7748
@@ -123,7 +115,7 @@ class TestX25519Exchange(object):
binascii.unhexlify(
b"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98"
b"eaa9b4e6a"
- )
+ ),
),
(
binascii.unhexlify(
@@ -133,24 +125,33 @@ class TestX25519Exchange(object):
binascii.unhexlify(
b"de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e1"
b"46f882b4f"
- )
- )
- ]
+ ),
+ ),
+ ],
)
def test_pub_priv_bytes_raw(self, private_bytes, public_bytes, backend):
private_key = X25519PrivateKey.from_private_bytes(private_bytes)
- assert private_key.private_bytes(
- serialization.Encoding.Raw,
- serialization.PrivateFormat.Raw,
- serialization.NoEncryption()
- ) == private_bytes
- assert private_key.public_key().public_bytes(
- serialization.Encoding.Raw, serialization.PublicFormat.Raw
- ) == public_bytes
+ assert (
+ private_key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.Raw,
+ serialization.NoEncryption(),
+ )
+ == private_bytes
+ )
+ assert (
+ private_key.public_key().public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+ == public_bytes
+ )
public_key = X25519PublicKey.from_public_bytes(public_bytes)
- assert public_key.public_bytes(
- serialization.Encoding.Raw, serialization.PublicFormat.Raw
- ) == public_bytes
+ assert (
+ public_key.public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+ == public_bytes
+ )
def test_generate(self, backend):
key = X25519PrivateKey.generate()
@@ -182,21 +183,21 @@ class TestX25519Exchange(object):
key.private_bytes(
serialization.Encoding.Raw,
serialization.PrivateFormat.Raw,
- None
+ None,
)
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.Raw,
serialization.PrivateFormat.PKCS8,
- None
+ None,
)
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.Raw,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_invalid_public_bytes(self, backend):
@@ -204,19 +205,17 @@ class TestX25519Exchange(object):
with pytest.raises(ValueError):
key.public_bytes(
serialization.Encoding.Raw,
- serialization.PublicFormat.SubjectPublicKeyInfo
+ serialization.PublicFormat.SubjectPublicKeyInfo,
)
with pytest.raises(ValueError):
key.public_bytes(
- serialization.Encoding.PEM,
- serialization.PublicFormat.PKCS1
+ serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
)
with pytest.raises(ValueError):
key.public_bytes(
- serialization.Encoding.PEM,
- serialization.PublicFormat.Raw
+ serialization.Encoding.PEM, serialization.PublicFormat.Raw
)
@pytest.mark.parametrize(
@@ -227,33 +226,34 @@ class TestX25519Exchange(object):
serialization.PrivateFormat.PKCS8,
serialization.BestAvailableEncryption(b"password"),
b"password",
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
),
(
serialization.Encoding.DER,
serialization.PrivateFormat.PKCS8,
serialization.BestAvailableEncryption(b"password"),
b"password",
- serialization.load_der_private_key
+ serialization.load_der_private_key,
),
(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
serialization.NoEncryption(),
None,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
),
(
serialization.Encoding.DER,
serialization.PrivateFormat.PKCS8,
serialization.NoEncryption(),
None,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
),
- ]
+ ],
)
- def test_round_trip_private_serialization(self, encoding, fmt, encryption,
- passwd, load_func, backend):
+ def test_round_trip_private_serialization(
+ self, encoding, fmt, encryption, passwd, load_func, backend
+ ):
key = X25519PrivateKey.generate()
serialized = key.private_bytes(encoding, fmt, encryption)
loaded_key = load_func(serialized, passwd, backend)
@@ -262,8 +262,11 @@ class TestX25519Exchange(object):
def test_buffer_protocol(self, backend):
private_bytes = bytearray(os.urandom(32))
key = X25519PrivateKey.from_private_bytes(private_bytes)
- assert key.private_bytes(
- serialization.Encoding.Raw,
- serialization.PrivateFormat.Raw,
- serialization.NoEncryption()
- ) == private_bytes
+ assert (
+ key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.Raw,
+ serialization.NoEncryption(),
+ )
+ == private_bytes
+ )
diff --git a/tests/hazmat/primitives/test_x448.py b/tests/hazmat/primitives/test_x448.py
index 817de76f2..7b19b65ee 100644
--- a/tests/hazmat/primitives/test_x448.py
+++ b/tests/hazmat/primitives/test_x448.py
@@ -10,22 +10,23 @@ import os
import pytest
from cryptography.exceptions import _Reasons
-from cryptography.hazmat.backends.interfaces import DHBackend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.x448 import (
- X448PrivateKey, X448PublicKey
+ X448PrivateKey,
+ X448PublicKey,
)
from ...utils import (
- load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
@pytest.mark.supported(
only_if=lambda backend: not backend.x448_supported(),
- skip_message="Requires OpenSSL without X448 support"
+ skip_message="Requires OpenSSL without X448 support",
)
-@pytest.mark.requires_backend_interface(interface=DHBackend)
def test_x448_unsupported(backend):
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM):
X448PublicKey.from_public_bytes(b"0" * 56)
@@ -39,16 +40,15 @@ def test_x448_unsupported(backend):
@pytest.mark.supported(
only_if=lambda backend: backend.x448_supported(),
- skip_message="Requires OpenSSL with X448 support"
+ skip_message="Requires OpenSSL with X448 support",
)
-@pytest.mark.requires_backend_interface(interface=DHBackend)
class TestX448Exchange(object):
@pytest.mark.parametrize(
"vector",
load_vectors_from_file(
os.path.join("asymmetric", "X448", "rfc7748.txt"),
- load_nist_vectors
- )
+ load_nist_vectors,
+ ),
)
def test_rfc7748(self, vector, backend):
private = binascii.unhexlify(vector["input_scalar"])
@@ -93,7 +93,7 @@ class TestX448Exchange(object):
binascii.unhexlify(
b"9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c"
b"22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0"
- )
+ ),
),
(
binascii.unhexlify(
@@ -103,24 +103,33 @@ class TestX448Exchange(object):
binascii.unhexlify(
b"3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b430"
b"27d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609"
- )
- )
- ]
+ ),
+ ),
+ ],
)
def test_pub_priv_bytes_raw(self, private_bytes, public_bytes, backend):
private_key = X448PrivateKey.from_private_bytes(private_bytes)
- assert private_key.private_bytes(
- serialization.Encoding.Raw,
- serialization.PrivateFormat.Raw,
- serialization.NoEncryption()
- ) == private_bytes
- assert private_key.public_key().public_bytes(
- serialization.Encoding.Raw, serialization.PublicFormat.Raw
- ) == public_bytes
+ assert (
+ private_key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.Raw,
+ serialization.NoEncryption(),
+ )
+ == private_bytes
+ )
+ assert (
+ private_key.public_key().public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+ == public_bytes
+ )
public_key = X448PublicKey.from_public_bytes(public_bytes)
- assert public_key.public_bytes(
- serialization.Encoding.Raw, serialization.PublicFormat.Raw
- ) == public_bytes
+ assert (
+ public_key.public_bytes(
+ serialization.Encoding.Raw, serialization.PublicFormat.Raw
+ )
+ == public_bytes
+ )
@pytest.mark.parametrize(
("encoding", "fmt", "encryption", "passwd", "load_func"),
@@ -130,33 +139,34 @@ class TestX448Exchange(object):
serialization.PrivateFormat.PKCS8,
serialization.BestAvailableEncryption(b"password"),
b"password",
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
),
(
serialization.Encoding.DER,
serialization.PrivateFormat.PKCS8,
serialization.BestAvailableEncryption(b"password"),
b"password",
- serialization.load_der_private_key
+ serialization.load_der_private_key,
),
(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
serialization.NoEncryption(),
None,
- serialization.load_pem_private_key
+ serialization.load_pem_private_key,
),
(
serialization.Encoding.DER,
serialization.PrivateFormat.PKCS8,
serialization.NoEncryption(),
None,
- serialization.load_der_private_key
+ serialization.load_der_private_key,
),
- ]
+ ],
)
- def test_round_trip_private_serialization(self, encoding, fmt, encryption,
- passwd, load_func, backend):
+ def test_round_trip_private_serialization(
+ self, encoding, fmt, encryption, passwd, load_func, backend
+ ):
key = X448PrivateKey.generate()
serialized = key.private_bytes(encoding, fmt, encryption)
loaded_key = load_func(serialized, passwd, backend)
@@ -192,21 +202,21 @@ class TestX448Exchange(object):
key.private_bytes(
serialization.Encoding.Raw,
serialization.PrivateFormat.Raw,
- None
+ None,
)
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.Raw,
serialization.PrivateFormat.PKCS8,
- None
+ None,
)
with pytest.raises(ValueError):
key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.Raw,
- serialization.NoEncryption()
+ serialization.NoEncryption(),
)
def test_invalid_public_bytes(self, backend):
@@ -214,19 +224,17 @@ class TestX448Exchange(object):
with pytest.raises(ValueError):
key.public_bytes(
serialization.Encoding.Raw,
- serialization.PublicFormat.SubjectPublicKeyInfo
+ serialization.PublicFormat.SubjectPublicKeyInfo,
)
with pytest.raises(ValueError):
key.public_bytes(
- serialization.Encoding.PEM,
- serialization.PublicFormat.PKCS1
+ serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
)
with pytest.raises(ValueError):
key.public_bytes(
- serialization.Encoding.PEM,
- serialization.PublicFormat.Raw
+ serialization.Encoding.PEM, serialization.PublicFormat.Raw
)
def test_buffer_protocol(self, backend):
@@ -235,8 +243,11 @@ class TestX448Exchange(object):
b"d9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b"
)
key = X448PrivateKey.from_private_bytes(bytearray(private_bytes))
- assert key.private_bytes(
- serialization.Encoding.Raw,
- serialization.PrivateFormat.Raw,
- serialization.NoEncryption()
- ) == private_bytes
+ assert (
+ key.private_bytes(
+ serialization.Encoding.Raw,
+ serialization.PrivateFormat.Raw,
+ serialization.NoEncryption(),
+ )
+ == private_bytes
+ )
diff --git a/tests/hazmat/primitives/test_x963_vectors.py b/tests/hazmat/primitives/test_x963_vectors.py
index 4a945d470..e3b54fc15 100644
--- a/tests/hazmat/primitives/test_x963_vectors.py
+++ b/tests/hazmat/primitives/test_x963_vectors.py
@@ -9,7 +9,6 @@ import os
import pytest
-from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.backends.interfaces import HashBackend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
@@ -21,7 +20,7 @@ from ...utils import load_vectors_from_file, load_x963_vectors
def _skip_hashfn_unsupported(backend, hashfn):
if not backend.hash_supported(hashfn):
pytest.skip(
- "Hash {0} is not supported by this backend {1}".format(
+ "Hash {} is not supported by this backend {}".format(
hashfn.name, backend
)
)
@@ -30,19 +29,18 @@ def _skip_hashfn_unsupported(backend, hashfn):
@pytest.mark.requires_backend_interface(interface=HashBackend)
class TestX963(object):
_algorithms_dict = {
- 'SHA-1': hashes.SHA1,
- 'SHA-224': hashes.SHA224,
- 'SHA-256': hashes.SHA256,
- 'SHA-384': hashes.SHA384,
- 'SHA-512': hashes.SHA512
+ "SHA-1": hashes.SHA1,
+ "SHA-224": hashes.SHA224,
+ "SHA-256": hashes.SHA256,
+ "SHA-384": hashes.SHA384,
+ "SHA-512": hashes.SHA512,
}
@pytest.mark.parametrize(
("vector"),
load_vectors_from_file(
- os.path.join("KDF", "ansx963_2001.txt"),
- load_x963_vectors
- )
+ os.path.join("KDF", "ansx963_2001.txt"), load_x963_vectors
+ ),
)
def test_x963(self, backend, vector):
hashfn = self._algorithms_dict[vector["hash"]]
@@ -55,10 +53,12 @@ class TestX963(object):
key_data_len = vector["key_data_length"] // 8
key_data = binascii.unhexlify(vector["key_data"])
- xkdf = X963KDF(algorithm=hashfn(),
- length=key_data_len,
- sharedinfo=sharedinfo,
- backend=default_backend())
+ xkdf = X963KDF(
+ algorithm=hashfn(),
+ length=key_data_len,
+ sharedinfo=sharedinfo,
+ backend=backend,
+ )
xkdf.verify(key, key_data)
def test_unsupported_hash(self, backend):
diff --git a/tests/hazmat/primitives/test_x963kdf.py b/tests/hazmat/primitives/test_x963kdf.py
index c4dd89252..5040ae41e 100644
--- a/tests/hazmat/primitives/test_x963kdf.py
+++ b/tests/hazmat/primitives/test_x963kdf.py
@@ -8,9 +8,7 @@ import binascii
import pytest
-from cryptography.exceptions import (
- AlreadyFinalized, InvalidKey, _Reasons
-)
+from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons
from cryptography.hazmat.backends.interfaces import HashBackend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
@@ -46,9 +44,11 @@ class TestX963KDF(object):
assert xkdf.derive(key) == derivedkey
def test_buffer_protocol(self, backend):
- key = bytearray(binascii.unhexlify(
- b"96c05619d56c328ab95fe84b18264b08725b85e33fd34f08"
- ))
+ key = bytearray(
+ binascii.unhexlify(
+ b"96c05619d56c328ab95fe84b18264b08725b85e33fd34f08"
+ )
+ )
derivedkey = binascii.unhexlify(b"443024c3dae66b95e6f5670601558f71")
@@ -86,39 +86,25 @@ class TestX963KDF(object):
def test_unicode_typeerror(self, backend):
with pytest.raises(TypeError):
- X963KDF(
- hashes.SHA256(),
- 16,
- sharedinfo=u"foo",
- backend=backend
- )
+ X963KDF(hashes.SHA256(), 16, sharedinfo=u"foo", backend=backend)
with pytest.raises(TypeError):
xkdf = X963KDF(
- hashes.SHA256(),
- 16,
- sharedinfo=None,
- backend=backend
+ hashes.SHA256(), 16, sharedinfo=None, backend=backend
)
xkdf.derive(u"foo")
with pytest.raises(TypeError):
xkdf = X963KDF(
- hashes.SHA256(),
- 16,
- sharedinfo=None,
- backend=backend
+ hashes.SHA256(), 16, sharedinfo=None, backend=backend
)
xkdf.verify(u"foo", b"bar")
with pytest.raises(TypeError):
xkdf = X963KDF(
- hashes.SHA256(),
- 16,
- sharedinfo=None,
- backend=backend
+ hashes.SHA256(), 16, sharedinfo=None, backend=backend
)
xkdf.verify(b"foo", u"bar")
diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py
index 14cb08a89..08bfd7ebe 100644
--- a/tests/hazmat/primitives/twofactor/test_hotp.py
+++ b/tests/hazmat/primitives/twofactor/test_hotp.py
@@ -16,16 +16,17 @@ from cryptography.hazmat.primitives.twofactor import InvalidToken
from cryptography.hazmat.primitives.twofactor.hotp import HOTP
from ....utils import (
- load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
-vectors = load_vectors_from_file(
- "twofactor/rfc-4226.txt", load_nist_vectors)
+vectors = load_vectors_from_file("twofactor/rfc-4226.txt", load_nist_vectors)
@pytest.mark.supported(
only_if=lambda backend: backend.hmac_supported(hashes.SHA1()),
- skip_message="Does not support HMAC-SHA1."
+ skip_message="Does not support HMAC-SHA1.",
)
@pytest.mark.requires_backend_interface(interface=HMACBackend)
class TestHOTP(object):
@@ -102,12 +103,14 @@ class TestHOTP(object):
assert hotp.get_provisioning_uri("Alice Smith", 1, None) == (
"otpauth://hotp/Alice%20Smith?digits=6&secret=GEZDGNBV"
- "GY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&counter=1")
+ "GY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&counter=1"
+ )
- assert hotp.get_provisioning_uri("Alice Smith", 1, 'Foo') == (
+ assert hotp.get_provisioning_uri("Alice Smith", 1, "Foo") == (
"otpauth://hotp/Foo:Alice%20Smith?digits=6&secret=GEZD"
"GNBVGY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&issuer=Foo"
- "&counter=1")
+ "&counter=1"
+ )
def test_buffer_protocol(self, backend):
key = bytearray(b"a long key with lots of entropy goes here")
diff --git a/tests/hazmat/primitives/twofactor/test_totp.py b/tests/hazmat/primitives/twofactor/test_totp.py
index 59d875afe..06d86008a 100644
--- a/tests/hazmat/primitives/twofactor/test_totp.py
+++ b/tests/hazmat/primitives/twofactor/test_totp.py
@@ -13,21 +13,23 @@ from cryptography.hazmat.primitives.twofactor import InvalidToken
from cryptography.hazmat.primitives.twofactor.totp import TOTP
from ....utils import (
- load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+ load_nist_vectors,
+ load_vectors_from_file,
+ raises_unsupported_algorithm,
)
-vectors = load_vectors_from_file(
- "twofactor/rfc-6238.txt", load_nist_vectors)
+vectors = load_vectors_from_file("twofactor/rfc-6238.txt", load_nist_vectors)
@pytest.mark.requires_backend_interface(interface=HMACBackend)
class TestTOTP(object):
@pytest.mark.supported(
only_if=lambda backend: backend.hmac_supported(hashes.SHA1()),
- skip_message="Does not support HMAC-SHA1."
+ skip_message="Does not support HMAC-SHA1.",
)
@pytest.mark.parametrize(
- "params", [i for i in vectors if i["mode"] == b"SHA1"])
+ "params", [i for i in vectors if i["mode"] == b"SHA1"]
+ )
def test_generate_sha1(self, backend, params):
secret = params["secret"]
time = int(params["time"])
@@ -38,10 +40,11 @@ class TestTOTP(object):
@pytest.mark.supported(
only_if=lambda backend: backend.hmac_supported(hashes.SHA256()),
- skip_message="Does not support HMAC-SHA256."
+ skip_message="Does not support HMAC-SHA256.",
)
@pytest.mark.parametrize(
- "params", [i for i in vectors if i["mode"] == b"SHA256"])
+ "params", [i for i in vectors if i["mode"] == b"SHA256"]
+ )
def test_generate_sha256(self, backend, params):
secret = params["secret"]
time = int(params["time"])
@@ -52,10 +55,11 @@ class TestTOTP(object):
@pytest.mark.supported(
only_if=lambda backend: backend.hmac_supported(hashes.SHA512()),
- skip_message="Does not support HMAC-SHA512."
+ skip_message="Does not support HMAC-SHA512.",
)
@pytest.mark.parametrize(
- "params", [i for i in vectors if i["mode"] == b"SHA512"])
+ "params", [i for i in vectors if i["mode"] == b"SHA512"]
+ )
def test_generate_sha512(self, backend, params):
secret = params["secret"]
time = int(params["time"])
@@ -66,10 +70,11 @@ class TestTOTP(object):
@pytest.mark.supported(
only_if=lambda backend: backend.hmac_supported(hashes.SHA1()),
- skip_message="Does not support HMAC-SHA1."
+ skip_message="Does not support HMAC-SHA1.",
)
@pytest.mark.parametrize(
- "params", [i for i in vectors if i["mode"] == b"SHA1"])
+ "params", [i for i in vectors if i["mode"] == b"SHA1"]
+ )
def test_verify_sha1(self, backend, params):
secret = params["secret"]
time = int(params["time"])
@@ -81,10 +86,11 @@ class TestTOTP(object):
@pytest.mark.supported(
only_if=lambda backend: backend.hmac_supported(hashes.SHA256()),
- skip_message="Does not support HMAC-SHA256."
+ skip_message="Does not support HMAC-SHA256.",
)
@pytest.mark.parametrize(
- "params", [i for i in vectors if i["mode"] == b"SHA256"])
+ "params", [i for i in vectors if i["mode"] == b"SHA256"]
+ )
def test_verify_sha256(self, backend, params):
secret = params["secret"]
time = int(params["time"])
@@ -96,10 +102,11 @@ class TestTOTP(object):
@pytest.mark.supported(
only_if=lambda backend: backend.hmac_supported(hashes.SHA512()),
- skip_message="Does not support HMAC-SHA512."
+ skip_message="Does not support HMAC-SHA512.",
)
@pytest.mark.parametrize(
- "params", [i for i in vectors if i["mode"] == b"SHA512"])
+ "params", [i for i in vectors if i["mode"] == b"SHA512"]
+ )
def test_verify_sha512(self, backend, params):
secret = params["secret"]
time = int(params["time"])
@@ -132,12 +139,14 @@ class TestTOTP(object):
assert totp.get_provisioning_uri("Alice Smith", None) == (
"otpauth://totp/Alice%20Smith?digits=6&secret=GEZDGNBVG"
- "Y3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&period=30")
+ "Y3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&period=30"
+ )
- assert totp.get_provisioning_uri("Alice Smith", 'World') == (
+ assert totp.get_provisioning_uri("Alice Smith", "World") == (
"otpauth://totp/World:Alice%20Smith?digits=6&secret=GEZ"
"DGNBVGY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&issuer=World"
- "&period=30")
+ "&period=30"
+ )
def test_buffer_protocol(self, backend):
key = bytearray(b"a long key with lots of entropy goes here")
diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py
index 811dcf905..3f1eff66e 100644
--- a/tests/hazmat/primitives/utils.py
+++ b/tests/hazmat/primitives/utils.py
@@ -11,15 +11,21 @@ import os
import pytest
from cryptography.exceptions import (
- AlreadyFinalized, AlreadyUpdated, InvalidSignature, InvalidTag,
- NotYetFinalized
+ AlreadyFinalized,
+ AlreadyUpdated,
+ InvalidSignature,
+ InvalidTag,
+ NotYetFinalized,
)
-from cryptography.hazmat.primitives import hashes, hmac
+from cryptography.hazmat.primitives import hashes, hmac, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.ciphers import Cipher
+from cryptography.hazmat.primitives.ciphers.modes import GCM
from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand
from cryptography.hazmat.primitives.kdf.kbkdf import (
- CounterLocation, KBKDFHMAC, Mode
+ CounterLocation,
+ KBKDFHMAC,
+ Mode,
)
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
@@ -35,8 +41,9 @@ def _load_all_params(path, file_names, param_loader):
return all_params
-def generate_encrypt_test(param_loader, path, file_names, cipher_factory,
- mode_factory):
+def generate_encrypt_test(
+ param_loader, path, file_names, cipher_factory, mode_factory
+):
all_params = _load_all_params(path, file_names, param_loader)
@pytest.mark.parametrize("params", all_params)
@@ -54,9 +61,7 @@ def encrypt_test(backend, cipher_factory, mode_factory, params):
plaintext = params["plaintext"]
ciphertext = params["ciphertext"]
cipher = Cipher(
- cipher_factory(**params),
- mode_factory(**params),
- backend=backend
+ cipher_factory(**params), mode_factory(**params), backend=backend
)
encryptor = cipher.encryptor()
actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
@@ -68,8 +73,9 @@ def encrypt_test(backend, cipher_factory, mode_factory, params):
assert actual_plaintext == binascii.unhexlify(plaintext)
-def generate_aead_test(param_loader, path, file_names, cipher_factory,
- mode_factory):
+def generate_aead_test(
+ param_loader, path, file_names, cipher_factory, mode_factory
+):
all_params = _load_all_params(path, file_names, param_loader)
@pytest.mark.parametrize("params", all_params)
@@ -80,6 +86,20 @@ def generate_aead_test(param_loader, path, file_names, cipher_factory,
def aead_test(backend, cipher_factory, mode_factory, params):
+ if mode_factory is GCM and len(params["iv"]) < 16:
+ # 16 because this is hex encoded data
+ pytest.skip("Less than 64-bit IVs are no longer supported")
+
+ if (
+ mode_factory is GCM
+ and backend._fips_enabled
+ and len(params["iv"]) != 24
+ ):
+ # Red Hat disables non-96-bit IV support as part of its FIPS
+ # patches. The check is for a byte length of 24 because the value is
+ # hex encoded.
+ pytest.skip("Non-96-bit IVs unsupported in FIPS mode.")
+
if params.get("pt") is not None:
plaintext = params["pt"]
ciphertext = params["ct"]
@@ -87,10 +107,12 @@ def aead_test(backend, cipher_factory, mode_factory, params):
if params.get("fail") is True:
cipher = Cipher(
cipher_factory(binascii.unhexlify(params["key"])),
- mode_factory(binascii.unhexlify(params["iv"]),
- binascii.unhexlify(params["tag"]),
- len(binascii.unhexlify(params["tag"]))),
- backend
+ mode_factory(
+ binascii.unhexlify(params["iv"]),
+ binascii.unhexlify(params["tag"]),
+ len(binascii.unhexlify(params["tag"])),
+ ),
+ backend,
)
decryptor = cipher.decryptor()
decryptor.authenticate_additional_data(binascii.unhexlify(aad))
@@ -101,7 +123,7 @@ def aead_test(backend, cipher_factory, mode_factory, params):
cipher = Cipher(
cipher_factory(binascii.unhexlify(params["key"])),
mode_factory(binascii.unhexlify(params["iv"]), None),
- backend
+ backend,
)
encryptor = cipher.encryptor()
encryptor.authenticate_additional_data(binascii.unhexlify(aad))
@@ -111,10 +133,12 @@ def aead_test(backend, cipher_factory, mode_factory, params):
assert binascii.hexlify(encryptor.tag[:tag_len]) == params["tag"]
cipher = Cipher(
cipher_factory(binascii.unhexlify(params["key"])),
- mode_factory(binascii.unhexlify(params["iv"]),
- binascii.unhexlify(params["tag"]),
- min_tag_length=tag_len),
- backend
+ mode_factory(
+ binascii.unhexlify(params["iv"]),
+ binascii.unhexlify(params["tag"]),
+ min_tag_length=tag_len,
+ ),
+ backend,
)
decryptor = cipher.decryptor()
decryptor.authenticate_additional_data(binascii.unhexlify(aad))
@@ -123,13 +147,15 @@ def aead_test(backend, cipher_factory, mode_factory, params):
assert actual_plaintext == binascii.unhexlify(plaintext)
-def generate_stream_encryption_test(param_loader, path, file_names,
- cipher_factory):
+def generate_stream_encryption_test(
+ param_loader, path, file_names, cipher_factory
+):
all_params = _load_all_params(path, file_names, param_loader)
@pytest.mark.parametrize("params", all_params)
def test_stream_encryption(self, backend, params):
stream_encryption_test(backend, cipher_factory, params)
+
return test_stream_encryption
@@ -157,6 +183,7 @@ def generate_hash_test(param_loader, path, file_names, hash_cls):
@pytest.mark.parametrize("params", all_params)
def test_hash(self, backend, params):
hash_test(backend, hash_cls, params)
+
return test_hash
@@ -171,6 +198,7 @@ def hash_test(backend, algorithm, params):
def generate_base_hash_test(algorithm, digest_size):
def test_base_hash(self, backend):
base_hash_test(backend, algorithm, digest_size)
+
return test_base_hash
@@ -191,6 +219,7 @@ def base_hash_test(backend, algorithm, digest_size):
def generate_base_hmac_test(hash_cls):
def test_base_hmac(self, backend):
base_hmac_test(backend, hash_cls)
+
return test_base_hmac
@@ -208,6 +237,7 @@ def generate_hmac_test(param_loader, path, file_names, algorithm):
@pytest.mark.parametrize("params", all_params)
def test_hmac(self, backend, params):
hmac_test(backend, algorithm, params)
+
return test_hmac
@@ -224,6 +254,7 @@ def generate_pbkdf2_test(param_loader, path, file_names, algorithm):
@pytest.mark.parametrize("params", all_params)
def test_pbkdf2(self, backend, params):
pbkdf2_test(backend, algorithm, params)
+
return test_pbkdf2
@@ -236,7 +267,7 @@ def pbkdf2_test(backend, algorithm, params):
int(params["length"]),
params["salt"],
int(params["iterations"]),
- backend
+ backend,
)
derived_key = kdf.derive(params["password"])
assert binascii.hexlify(derived_key) == params["derived_key"]
@@ -245,6 +276,7 @@ def pbkdf2_test(backend, algorithm, params):
def generate_aead_exception_test(cipher_factory, mode_factory):
def test_aead_exception(self, backend):
aead_exception_test(backend, cipher_factory, mode_factory)
+
return test_aead_exception
@@ -252,7 +284,7 @@ def aead_exception_test(backend, cipher_factory, mode_factory):
cipher = Cipher(
cipher_factory(binascii.unhexlify(b"0" * 32)),
mode_factory(binascii.unhexlify(b"0" * 24)),
- backend
+ backend,
)
encryptor = cipher.encryptor()
encryptor.update(b"a" * 16)
@@ -270,7 +302,7 @@ def aead_exception_test(backend, cipher_factory, mode_factory):
cipher = Cipher(
cipher_factory(binascii.unhexlify(b"0" * 32)),
mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
- backend
+ backend,
)
decryptor = cipher.decryptor()
decryptor.update(b"a" * 16)
@@ -281,6 +313,7 @@ def aead_exception_test(backend, cipher_factory, mode_factory):
def generate_aead_tag_exception_test(cipher_factory, mode_factory):
def test_aead_tag_exception(self, backend):
aead_tag_exception_test(backend, cipher_factory, mode_factory)
+
return test_aead_tag_exception
@@ -288,7 +321,7 @@ def aead_tag_exception_test(backend, cipher_factory, mode_factory):
cipher = Cipher(
cipher_factory(binascii.unhexlify(b"0" * 32)),
mode_factory(binascii.unhexlify(b"0" * 24)),
- backend
+ backend,
)
with pytest.raises(ValueError):
@@ -300,7 +333,7 @@ def aead_tag_exception_test(backend, cipher_factory, mode_factory):
cipher = Cipher(
cipher_factory(binascii.unhexlify(b"0" * 32)),
mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
- backend
+ backend,
)
with pytest.raises(ValueError):
cipher.encryptor()
@@ -312,7 +345,7 @@ def hkdf_derive_test(backend, algorithm, params):
int(params["l"]),
salt=binascii.unhexlify(params["salt"]) or None,
info=binascii.unhexlify(params["info"]) or None,
- backend=backend
+ backend=backend,
)
okm = hkdf.derive(binascii.unhexlify(params["ikm"]))
@@ -326,7 +359,7 @@ def hkdf_extract_test(backend, algorithm, params):
int(params["l"]),
salt=binascii.unhexlify(params["salt"]) or None,
info=binascii.unhexlify(params["info"]) or None,
- backend=backend
+ backend=backend,
)
prk = hkdf._extract(binascii.unhexlify(params["ikm"]))
@@ -339,7 +372,7 @@ def hkdf_expand_test(backend, algorithm, params):
algorithm,
int(params["l"]),
info=binascii.unhexlify(params["info"]) or None,
- backend=backend
+ backend=backend,
)
okm = hkdf.derive(binascii.unhexlify(params["prk"]))
@@ -353,8 +386,7 @@ def generate_hkdf_test(param_loader, path, file_names, algorithm):
all_tests = [hkdf_extract_test, hkdf_expand_test, hkdf_derive_test]
@pytest.mark.parametrize(
- ("params", "hkdf_test"),
- itertools.product(all_params, all_tests)
+ ("params", "hkdf_test"), itertools.product(all_params, all_tests)
)
def test_hkdf(self, backend, params, hkdf_test):
hkdf_test(backend, algorithm, params)
@@ -368,16 +400,17 @@ def generate_kbkdf_counter_mode_test(param_loader, path, file_names):
@pytest.mark.parametrize("params", all_params)
def test_kbkdf(self, backend, params):
kbkdf_counter_mode_test(backend, params)
+
return test_kbkdf
def kbkdf_counter_mode_test(backend, params):
supported_algorithms = {
- 'hmac_sha1': hashes.SHA1,
- 'hmac_sha224': hashes.SHA224,
- 'hmac_sha256': hashes.SHA256,
- 'hmac_sha384': hashes.SHA384,
- 'hmac_sha512': hashes.SHA512,
+ "hmac_sha1": hashes.SHA1,
+ "hmac_sha224": hashes.SHA224,
+ "hmac_sha256": hashes.SHA256,
+ "hmac_sha384": hashes.SHA384,
+ "hmac_sha512": hashes.SHA512,
}
supported_counter_locations = {
@@ -385,39 +418,44 @@ def kbkdf_counter_mode_test(backend, params):
"after_fixed": CounterLocation.AfterFixed,
}
- algorithm = supported_algorithms.get(params.get('prf'))
+ algorithm = supported_algorithms.get(params.get("prf"))
if algorithm is None or not backend.hmac_supported(algorithm()):
- pytest.skip("KBKDF does not support algorithm: {0}".format(
- params.get('prf')
- ))
+ pytest.skip(
+ "KBKDF does not support algorithm: {}".format(params.get("prf"))
+ )
ctr_loc = supported_counter_locations.get(params.get("ctrlocation"))
if ctr_loc is None or not isinstance(ctr_loc, CounterLocation):
- pytest.skip("Does not support counter location: {0}".format(
- params.get('ctrlocation')
- ))
+ pytest.skip(
+ "Does not support counter location: {}".format(
+ params.get("ctrlocation")
+ )
+ )
ctrkdf = KBKDFHMAC(
algorithm(),
Mode.CounterMode,
- params['l'] // 8,
- params['rlen'] // 8,
+ params["l"] // 8,
+ params["rlen"] // 8,
None,
ctr_loc,
None,
None,
- binascii.unhexlify(params['fixedinputdata']),
- backend=backend)
+ binascii.unhexlify(params["fixedinputdata"]),
+ backend=backend,
+ )
- ko = ctrkdf.derive(binascii.unhexlify(params['ki']))
+ ko = ctrkdf.derive(binascii.unhexlify(params["ki"]))
assert binascii.hexlify(ko) == params["ko"]
-def generate_rsa_verification_test(param_loader, path, file_names, hash_alg,
- pad_factory):
+def generate_rsa_verification_test(
+ param_loader, path, file_names, hash_alg, pad_factory
+):
all_params = _load_all_params(path, file_names, param_loader)
- all_params = [i for i in all_params
- if i["algorithm"] == hash_alg.name.upper()]
+ all_params = [
+ i for i in all_params if i["algorithm"] == hash_alg.name.upper()
+ ]
@pytest.mark.parametrize("params", all_params)
def test_rsa_verification(self, backend, params):
@@ -428,8 +466,7 @@ def generate_rsa_verification_test(param_loader, path, file_names, hash_alg,
def rsa_verification_test(backend, params, hash_alg, pad_factory):
public_numbers = rsa.RSAPublicNumbers(
- e=params["public_exponent"],
- n=params["modulus"]
+ e=params["public_exponent"], n=params["modulus"]
)
public_key = public_numbers.public_key(backend)
pad = pad_factory(params, hash_alg)
@@ -437,19 +474,9 @@ def rsa_verification_test(backend, params, hash_alg, pad_factory):
msg = binascii.unhexlify(params["msg"])
if params["fail"]:
with pytest.raises(InvalidSignature):
- public_key.verify(
- signature,
- msg,
- pad,
- hash_alg
- )
+ public_key.verify(signature, msg, pad, hash_alg)
else:
- public_key.verify(
- signature,
- msg,
- pad,
- hash_alg
- )
+ public_key.verify(signature, msg, pad, hash_alg)
def _check_rsa_private_numbers(skey):
@@ -470,3 +497,13 @@ def _check_dsa_private_numbers(skey):
pkey = skey.public_numbers
params = pkey.parameter_numbers
assert pow(params.g, skey.x, params.p) == pkey.y
+
+
+def skip_fips_traditional_openssl(backend, fmt):
+ if (
+ fmt is serialization.PrivateFormat.TraditionalOpenSSL
+ and backend._fips_enabled
+ ):
+ pytest.skip(
+ "Traditional OpenSSL key format is not supported in FIPS mode."
+ )
diff --git a/tests/hazmat/test_der.py b/tests/hazmat/test_der.py
new file mode 100644
index 000000000..ef2052f50
--- /dev/null
+++ b/tests/hazmat/test_der.py
@@ -0,0 +1,232 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+from cryptography.hazmat._der import (
+ DERReader,
+ INTEGER,
+ NULL,
+ OCTET_STRING,
+ SEQUENCE,
+ encode_der,
+ encode_der_integer,
+)
+
+
+def test_der_reader_basic():
+ reader = DERReader(b"123456789")
+ assert reader.read_byte() == ord(b"1")
+ assert reader.read_bytes(1).tobytes() == b"2"
+ assert reader.read_bytes(4).tobytes() == b"3456"
+
+ with pytest.raises(ValueError):
+ reader.read_bytes(4)
+
+ assert reader.read_bytes(3).tobytes() == b"789"
+
+ # The input is now empty.
+ with pytest.raises(ValueError):
+ reader.read_bytes(1)
+ with pytest.raises(ValueError):
+ reader.read_byte()
+
+
+def test_der():
+ # This input is the following structure, using
+ # https://github.com/google/der-ascii
+ #
+ # SEQUENCE {
+ # SEQUENCE {
+ # NULL {}
+ # INTEGER { 42 }
+ # OCTET_STRING { "hello" }
+ # }
+ # }
+ der = b"\x30\x0e\x30\x0c\x05\x00\x02\x01\x2a\x04\x05\x68\x65\x6c\x6c\x6f"
+ reader = DERReader(der)
+ with pytest.raises(ValueError):
+ reader.check_empty()
+
+ with pytest.raises(ValueError):
+ with reader:
+ pass
+
+ with pytest.raises(ZeroDivisionError):
+ with DERReader(der):
+ raise ZeroDivisionError
+
+ # Parse the outer element.
+ outer = reader.read_element(SEQUENCE)
+ reader.check_empty()
+ assert outer.data.tobytes() == der[2:]
+
+ # Parse the outer element with read_any_element.
+ reader = DERReader(der)
+ tag, outer2 = reader.read_any_element()
+ reader.check_empty()
+ assert tag == SEQUENCE
+ assert outer2.data.tobytes() == der[2:]
+
+ # Parse the outer element with read_single_element.
+ outer3 = DERReader(der).read_single_element(SEQUENCE)
+ assert outer3.data.tobytes() == der[2:]
+
+ # read_single_element rejects trailing data.
+ with pytest.raises(ValueError):
+ DERReader(der + der).read_single_element(SEQUENCE)
+
+ # Continue parsing the structure.
+ inner = outer.read_element(SEQUENCE)
+ outer.check_empty()
+
+ # Parsing a missing optional element should work.
+ assert inner.read_optional_element(INTEGER) is None
+
+ null = inner.read_element(NULL)
+ null.check_empty()
+
+ # Parsing a present optional element should work.
+ integer = inner.read_optional_element(INTEGER)
+ assert integer.as_integer() == 42
+
+ octet_string = inner.read_element(OCTET_STRING)
+ assert octet_string.data.tobytes() == b"hello"
+
+ # Parsing a missing optional element should work when the input is empty.
+ inner.check_empty()
+ assert inner.read_optional_element(INTEGER) is None
+
+ # Re-encode the same structure.
+ der2 = encode_der(
+ SEQUENCE,
+ encode_der(
+ SEQUENCE,
+ encode_der(NULL),
+ encode_der(INTEGER, encode_der_integer(42)),
+ encode_der(OCTET_STRING, b"hello"),
+ ),
+ )
+ assert der2 == der
+
+
+@pytest.mark.parametrize(
+ "length,header",
+ [
+ # Single-byte lengths.
+ (0, b"\x04\x00"),
+ (1, b"\x04\x01"),
+ (2, b"\x04\x02"),
+ (127, b"\x04\x7f"),
+ # Long-form lengths.
+ (128, b"\x04\x81\x80"),
+ (129, b"\x04\x81\x81"),
+ (255, b"\x04\x81\xff"),
+ (0x100, b"\x04\x82\x01\x00"),
+ (0x101, b"\x04\x82\x01\x01"),
+ (0xFFFF, b"\x04\x82\xff\xff"),
+ (0x10000, b"\x04\x83\x01\x00\x00"),
+ ],
+)
+def test_der_lengths(length, header):
+ body = length * b"a"
+ der = header + body
+
+ reader = DERReader(der)
+ element = reader.read_element(OCTET_STRING)
+ reader.check_empty()
+ assert element.data.tobytes() == body
+
+ assert encode_der(OCTET_STRING, body) == der
+
+
+@pytest.mark.parametrize(
+ "bad_input",
+ [
+ # The input ended before the tag.
+ b"",
+ # The input ended before the length.
+ b"\x30",
+ # The input ended before the second byte of the length.
+ b"\x30\x81",
+ # The input ended before the body.
+ b"\x30\x01",
+ # The length used long form when it should be short form.
+ b"\x30\x81\x01\x00",
+ # The length was not minimally-encoded.
+ b"\x30\x82\x00\x80" + (0x80 * b"a"),
+ # Indefinite-length encoding is not valid DER.
+ b"\x30\x80\x00\x00"
+ # Tag number (the bottom 5 bits) 31 indicates long form tags, which we
+ # do not support.
+ b"\x1f\x00",
+ b"\x9f\x00",
+ b"\xbf\x00",
+ b"\xff\x00",
+ ],
+)
+def test_der_reader_bad_input(bad_input):
+ reader = DERReader(bad_input)
+ with pytest.raises(ValueError):
+ reader.read_any_element()
+
+
+def test_der_reader_wrong_tag():
+ reader = DERReader(b"\x04\x00")
+ with pytest.raises(ValueError):
+ reader.read_element(SEQUENCE)
+
+
+@pytest.mark.parametrize(
+ "value,der",
+ [
+ (0, b"\x00"),
+ (1, b"\x01"),
+ (2, b"\x02"),
+ (3, b"\x03"),
+ (127, b"\x7f"),
+ (128, b"\x00\x80"),
+ (
+ 0x112233445566778899AABBCCDDEEFF,
+ b"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ ),
+ ],
+)
+def test_integer(value, der):
+ assert encode_der_integer(value) == der
+ assert DERReader(der).as_integer() == value
+
+
+@pytest.mark.parametrize(
+ "bad_input",
+ [
+ # Zero is encoded as b"\x00", not the empty string.
+ b"",
+ # Too many leading zeros.
+ b"\x00\x00",
+ b"\x00\x7f",
+ # Too many leading ones.
+ b"\xff\xff",
+ b"\xff\x80",
+ # Negative integers are not supported.
+ b"\x80",
+ b"\x81",
+ b"\x80\x00\x00",
+ b"\xff",
+ ],
+)
+def test_invalid_integer(bad_input):
+ reader = DERReader(bad_input)
+ with pytest.raises(ValueError):
+ reader.as_integer()
+
+
+def test_invalid_integer_encode():
+ with pytest.raises(ValueError):
+ encode_der_integer(-1)
+
+ with pytest.raises(ValueError):
+ encode_der_integer("not an integer")
diff --git a/tests/hazmat/test_oid.py b/tests/hazmat/test_oid.py
new file mode 100644
index 000000000..5589ed976
--- /dev/null
+++ b/tests/hazmat/test_oid.py
@@ -0,0 +1,39 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+from cryptography.hazmat._oid import ObjectIdentifier
+
+
+def test_basic_oid():
+ assert ObjectIdentifier("1.2.3.4").dotted_string == "1.2.3.4"
+
+
+def test_oid_constraint():
+ # Too short
+ with pytest.raises(ValueError):
+ ObjectIdentifier("1")
+
+ # First node too big
+ with pytest.raises(ValueError):
+ ObjectIdentifier("3.2.1")
+
+ # Outside range
+ with pytest.raises(ValueError):
+ ObjectIdentifier("1.40")
+ with pytest.raises(ValueError):
+ ObjectIdentifier("0.42")
+
+ # non-decimal oid
+ with pytest.raises(ValueError):
+ ObjectIdentifier("1.2.foo.bar")
+ with pytest.raises(ValueError):
+ ObjectIdentifier("1.2.0xf00.0xba4")
+
+ # negative oid
+ with pytest.raises(ValueError):
+ ObjectIdentifier("1.2.-3.-4")
diff --git a/tests/test_cryptography_utils.py b/tests/test_cryptography_utils.py
index ddea7602c..0158ef351 100644
--- a/tests/test_cryptography_utils.py
+++ b/tests/test_cryptography_utils.py
@@ -58,8 +58,3 @@ class TestCachedProperty(object):
assert len(accesses) == 1
assert t.t == 14
assert len(accesses) == 1
-
-
-def test_bit_length():
- assert utils.bit_length(1) == 1
- assert utils.bit_length(11) == 4
diff --git a/tests/test_fernet.py b/tests/test_fernet.py
index 75ecc356a..38409b03e 100644
--- a/tests/test_fernet.py
+++ b/tests/test_fernet.py
@@ -6,7 +6,6 @@ from __future__ import absolute_import, division, print_function
import base64
import calendar
-import datetime
import json
import os
import time
@@ -27,14 +26,13 @@ import cryptography_vectors
def json_parametrize(keys, filename):
vector_file = cryptography_vectors.open_vector_file(
- os.path.join('fernet', filename), "r"
+ os.path.join("fernet", filename), "r"
)
with vector_file:
data = json.load(vector_file)
- return pytest.mark.parametrize(keys, [
- tuple([entry[k] for k in keys])
- for entry in data
- ])
+ return pytest.mark.parametrize(
+ keys, [tuple([entry[k] for k in keys]) for entry in data]
+ )
def test_default_backend():
@@ -52,24 +50,33 @@ def test_default_backend():
)
class TestFernet(object):
@json_parametrize(
- ("secret", "now", "iv", "src", "token"), "generate.json",
+ ("secret", "now", "iv", "src", "token"),
+ "generate.json",
)
def test_generate(self, secret, now, iv, src, token, backend):
f = Fernet(secret.encode("ascii"), backend=backend)
actual_token = f._encrypt_from_parts(
src.encode("ascii"),
calendar.timegm(iso8601.parse_date(now).utctimetuple()),
- b"".join(map(six.int2byte, iv))
+ b"".join(map(six.int2byte, iv)),
)
assert actual_token == token.encode("ascii")
@json_parametrize(
- ("secret", "now", "src", "ttl_sec", "token"), "verify.json",
+ ("secret", "now", "src", "ttl_sec", "token"),
+ "verify.json",
)
- def test_verify(self, secret, now, src, ttl_sec, token, backend,
- monkeypatch):
+ def test_verify(
+ self, secret, now, src, ttl_sec, token, backend, monkeypatch
+ ):
f = Fernet(secret.encode("ascii"), backend=backend)
current_time = calendar.timegm(iso8601.parse_date(now).utctimetuple())
+ payload = f.decrypt_at_time(
+ token.encode("ascii"),
+ ttl=ttl_sec,
+ current_time=current_time,
+ )
+ assert payload == src.encode("ascii")
monkeypatch.setattr(time, "time", lambda: current_time)
payload = f.decrypt(token.encode("ascii"), ttl=ttl_sec)
assert payload == src.encode("ascii")
@@ -78,6 +85,12 @@ class TestFernet(object):
def test_invalid(self, secret, token, now, ttl_sec, backend, monkeypatch):
f = Fernet(secret.encode("ascii"), backend=backend)
current_time = calendar.timegm(iso8601.parse_date(now).utctimetuple())
+ with pytest.raises(InvalidToken):
+ f.decrypt_at_time(
+ token.encode("ascii"),
+ ttl=ttl_sec,
+ current_time=current_time,
+ )
monkeypatch.setattr(time, "time", lambda: current_time)
with pytest.raises(InvalidToken):
f.decrypt(token.encode("ascii"), ttl=ttl_sec)
@@ -113,6 +126,13 @@ class TestFernet(object):
monkeypatch.setattr(time, "time", lambda: current_time)
assert f.decrypt(token, ttl=None) == pt
+ def test_ttl_required_in_decrypt_at_time(self, monkeypatch, backend):
+ f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend)
+ pt = b"encrypt me"
+ token = f.encrypt(pt)
+ with pytest.raises(ValueError):
+ f.decrypt_at_time(token, ttl=None, current_time=int(time.time()))
+
@pytest.mark.parametrize("message", [b"", b"Abc!", b"\x00\xFF\x00\x80"])
def test_roundtrips(self, message, backend):
f = Fernet(Fernet.generate_key(), backend=backend)
@@ -125,8 +145,7 @@ class TestFernet(object):
def test_extract_timestamp(self, monkeypatch, backend):
f = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend)
current_time = 1526138327
- monkeypatch.setattr(time, "time", lambda: current_time)
- token = f.encrypt(b'encrypt me')
+ token = f.encrypt_at_time(b"encrypt me", current_time)
assert f.extract_timestamp(token) == current_time
with pytest.raises(InvalidToken):
f.extract_timestamp(b"nonsensetoken")
@@ -159,6 +178,17 @@ class TestMultiFernet(object):
with pytest.raises(InvalidToken):
f.decrypt(b"\x00" * 16)
+ def test_decrypt_at_time(self, backend):
+ f1 = Fernet(base64.urlsafe_b64encode(b"\x00" * 32), backend=backend)
+ f = MultiFernet([f1])
+ pt = b"encrypt me"
+ token = f.encrypt_at_time(pt, current_time=100)
+ assert f.decrypt_at_time(token, ttl=1, current_time=100) == pt
+ with pytest.raises(InvalidToken):
+ f.decrypt_at_time(token, ttl=1, current_time=102)
+ with pytest.raises(ValueError):
+ f.decrypt_at_time(token, ttl=None, current_time=100)
+
def test_no_fernets(self, backend):
with pytest.raises(ValueError):
MultiFernet([])
@@ -195,18 +225,14 @@ class TestMultiFernet(object):
mf2 = MultiFernet([f2, f1])
plaintext = b"abc"
- mf1_ciphertext = mf1.encrypt(plaintext)
-
- later = datetime.datetime.now() + datetime.timedelta(minutes=5)
- later_time = time.mktime(later.timetuple())
- monkeypatch.setattr(time, "time", lambda: later_time)
+ original_time = int(time.time()) - 5 * 60
+ mf1_ciphertext = mf1.encrypt_at_time(plaintext, original_time)
- original_time, _ = Fernet._get_unverified_token_data(mf1_ciphertext)
rotated_time, _ = Fernet._get_unverified_token_data(
mf2.rotate(mf1_ciphertext)
)
- assert later_time != rotated_time
+ assert int(time.time()) != rotated_time
assert original_time == rotated_time
def test_rotate_decrypt_no_shared_keys(self, backend):
diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py
index 97df45a3d..042245f97 100644
--- a/tests/test_interfaces.py
+++ b/tests/test_interfaces.py
@@ -9,7 +9,9 @@ import pytest
import six
from cryptography.utils import (
- InterfaceNotImplemented, register_interface_if, verify_interface
+ InterfaceNotImplemented,
+ register_interface_if,
+ verify_interface,
)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index ecd257bda..d6afa3b34 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -18,13 +18,24 @@ from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
import cryptography_vectors
from .utils import (
- check_backend_support, load_cryptrec_vectors, load_ed25519_vectors,
- load_fips_dsa_key_pair_vectors, load_fips_dsa_sig_vectors,
- load_fips_ecdsa_key_pair_vectors, load_fips_ecdsa_signing_vectors,
- load_hash_vectors, load_kasvs_dh_vectors,
- load_kasvs_ecdh_vectors, load_nist_ccm_vectors, load_nist_kbkdf_vectors,
- load_nist_vectors, load_pkcs1_vectors, load_rsa_nist_vectors,
- load_vectors_from_file, load_x963_vectors, raises_unsupported_algorithm
+ check_backend_support,
+ load_cryptrec_vectors,
+ load_ed25519_vectors,
+ load_fips_dsa_key_pair_vectors,
+ load_fips_dsa_sig_vectors,
+ load_fips_ecdsa_key_pair_vectors,
+ load_fips_ecdsa_signing_vectors,
+ load_hash_vectors,
+ load_kasvs_dh_vectors,
+ load_kasvs_ecdh_vectors,
+ load_nist_ccm_vectors,
+ load_nist_kbkdf_vectors,
+ load_nist_vectors,
+ load_pkcs1_vectors,
+ load_rsa_nist_vectors,
+ load_vectors_from_file,
+ load_x963_vectors,
+ raises_unsupported_algorithm,
)
@@ -49,7 +60,8 @@ def test_check_backend_support_no_skip():
def test_load_nist_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.1
# Config info for aes_values
# AESVS GFSbox test data for CBC
@@ -84,7 +96,8 @@ def test_load_nist_vectors():
IV = 00000000000000000000000000000000
CIPHERTEXT = a9a1631bf4996954ebc093957b234589
PLAINTEXT = 9798c4640bad75c7c3227db910174e72
- """).splitlines()
+ """
+ ).splitlines()
assert load_nist_vectors(vector_data) == [
{
@@ -115,21 +128,19 @@ def test_load_nist_vectors():
def test_load_nist_vectors_with_null_chars():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
COUNT = 0
KEY = thing\\0withnulls
COUNT = 1
KEY = 00000000000000000000000000000000
- """).splitlines()
+ """
+ ).splitlines()
assert load_nist_vectors(vector_data) == [
- {
- "key": b"thing\x00withnulls",
- },
- {
- "key": b"00000000000000000000000000000000",
- },
+ {"key": b"thing\x00withnulls"},
+ {"key": b"00000000000000000000000000000000"},
]
@@ -172,7 +183,7 @@ def test_load_ed25519_vectors():
"e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490"
"1555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e"
"7a100b"
- )
+ ),
},
{
"secret_key": (
@@ -188,7 +199,7 @@ def test_load_ed25519_vectors():
"92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb6"
"9da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612"
"bb0c00"
- )
+ ),
},
{
"secret_key": (
@@ -204,7 +215,7 @@ def test_load_ed25519_vectors():
"6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac"
"3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea"
"1ec40a"
- )
+ ),
},
{
"secret_key": (
@@ -220,13 +231,14 @@ def test_load_ed25519_vectors():
"d9868d52c2bebce5f3fa5a79891970f309cb6591e3e1702a70276fa97c24b"
"3a8e58606c38c9758529da50ee31b8219cba45271c689afa60b0ea26c99db"
"19b00c"
- )
+ ),
},
]
def test_load_cryptrec_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# Vectors taken from https://info.isl.ntt.co.jp/crypt/eng/camellia/
# Download is t_camelia.txt
@@ -244,7 +256,8 @@ def test_load_cryptrec_vectors():
P No.001 : 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
C No.001 : 07 92 3A 39 EB 0A 81 7D 1C 4D 87 BD B8 2D 1F 1C
- """).splitlines()
+ """
+ ).splitlines()
assert load_cryptrec_vectors(vector_data) == [
{
@@ -266,21 +279,24 @@ def test_load_cryptrec_vectors():
def test_load_cryptrec_vectors_invalid():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# Vectors taken from https://info.isl.ntt.co.jp/crypt/eng/camellia/
# Download is t_camelia.txt
# Camellia with 128-bit key
E No.001 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- """).splitlines()
+ """
+ ).splitlines()
with pytest.raises(ValueError):
load_cryptrec_vectors(vector_data)
def test_load_hash_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# https://tools.ietf.org/html/rfc1321
[irrelevant]
@@ -300,7 +316,8 @@ def test_load_hash_vectors():
Len = 112
Msg = 6d65737361676520646967657374
MD = f96b697d7cb7938d525a2f31aaf161d0
- """).splitlines()
+ """
+ ).splitlines()
assert load_hash_vectors(vector_data) == [
(b"", "d41d8cd98f00b204e9800998ecf8427e"),
(b"61", "0cc175b9c0f1b6a831c399e269772661"),
@@ -310,29 +327,35 @@ def test_load_hash_vectors():
def test_load_hmac_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
Len = 224
# "Jefe"
Key = 4a656665
# "what do ya want for nothing?"
Msg = 7768617420646f2079612077616e7420666f72206e6f7468696e673f
MD = 750c783e6ab0b503eaa86e310a5db738
- """).splitlines()
+ """
+ ).splitlines()
assert load_hash_vectors(vector_data) == [
- (b"7768617420646f2079612077616e7420666f72206e6f7468696e673f",
- "750c783e6ab0b503eaa86e310a5db738",
- b"4a656665"),
+ (
+ b"7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "750c783e6ab0b503eaa86e310a5db738",
+ b"4a656665",
+ ),
]
def test_load_hash_vectors_bad_data():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# https://tools.ietf.org/html/rfc1321
Len = 0
Msg = 00
UNKNOWN=Hello World
- """).splitlines()
+ """
+ ).splitlines()
with pytest.raises(ValueError):
load_hash_vectors(vector_data)
@@ -357,7 +380,8 @@ def test_load_vectors_from_file():
def test_load_nist_gcm_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
[Keylen = 128]
[IVlen = 96]
[PTlen = 0]
@@ -447,67 +471,87 @@ def test_load_nist_gcm_vectors():
AAD =
Tag = eae841d4355feeb3f786bc86625f1e5b
FAIL
- """).splitlines()
+ """
+ ).splitlines()
assert load_nist_vectors(vector_data) == [
- {'aad': b'',
- 'pt': b'',
- 'iv': b'3c819d9a9bed087615030b65',
- 'tag': b'250327c674aaf477aef2675748cf6971',
- 'key': b'11754cd72aec309bf52f7687212e8957',
- 'ct': b''},
- {'aad': b'',
- 'pt': b'',
- 'iv': b'794ec588176c703d3d2a7a07',
- 'tag': b'b6e6f197168f5049aeda32dafbdaeb',
- 'key': b'272f16edb81a7abbea887357a58c1917',
- 'ct': b''},
- {'aad': b'',
- 'iv': b'907763b19b9b4ab6bd4f0281',
- 'tag': b'a2be08210d8c470a8df6e8fbd79ec5cf',
- 'key': b'a49a5e26a2f8cb63d05546c2a62f5343',
- 'ct': b'',
- 'fail': True},
- {'aad': b'e98e9d9c618e46fef32660976f854ee3',
- 'pt': b'd1448fa852b84408e2dad8381f363de7',
- 'iv': b'9549e4ba69a61cad7856efc1',
- 'tag': b'd72da7f5c6cf0bca7242c71835809449',
- 'key': b'5c1155084cc0ede76b3bc22e9f7574ef',
- 'ct': b'f78b60ca125218493bea1c50a2e12ef4'},
- {'aad': b'',
- 'pt': b'',
- 'iv': b'4e8df20faaf2c8eebe922902',
- 'tag': b'e39aeaebe86aa309a4d062d6274339',
- 'key': b'eac258e99c55e6ae8ef1da26640613d7',
- 'ct': b''},
- {'aad': b'',
- 'iv': b'55fef82cde693ce76efcc193',
- 'tag': b'3d68111a81ed22d2ef5bccac4fc27f',
- 'key': b'3726cf02fcc6b8639a5497652c94350d',
- 'ct': b'',
- 'fail': True},
- {'aad': b'',
- 'iv': b'eec51e7958c3f20a1bb71815',
- 'tag': b'a81886b3fb26e51fca87b267e1e157',
- 'key': b'f202299d5fd74f03b12d2119a6c4c038',
- 'ct': b'',
- 'fail': True},
- {'aad': b'',
- 'pt': b'',
- 'iv': b'f5cf3227444afd905a5f6dba',
- 'tag': b'1665b0f1a0b456e1664cfd3de08ccd',
- 'key': b'fd52925f39546b4c55ffb6b20c59898c',
- 'ct': b''},
- {'aad': b'',
- 'iv': b'3c',
- 'tag': b'eae841d4355feeb3f786bc86625f1e5b',
- 'key': b'58fab7632bcf10d2bcee58520bf37414',
- 'ct': b'15c4db4cbb451211179d57017f',
- 'fail': True},
+ {
+ "aad": b"",
+ "pt": b"",
+ "iv": b"3c819d9a9bed087615030b65",
+ "tag": b"250327c674aaf477aef2675748cf6971",
+ "key": b"11754cd72aec309bf52f7687212e8957",
+ "ct": b"",
+ },
+ {
+ "aad": b"",
+ "pt": b"",
+ "iv": b"794ec588176c703d3d2a7a07",
+ "tag": b"b6e6f197168f5049aeda32dafbdaeb",
+ "key": b"272f16edb81a7abbea887357a58c1917",
+ "ct": b"",
+ },
+ {
+ "aad": b"",
+ "iv": b"907763b19b9b4ab6bd4f0281",
+ "tag": b"a2be08210d8c470a8df6e8fbd79ec5cf",
+ "key": b"a49a5e26a2f8cb63d05546c2a62f5343",
+ "ct": b"",
+ "fail": True,
+ },
+ {
+ "aad": b"e98e9d9c618e46fef32660976f854ee3",
+ "pt": b"d1448fa852b84408e2dad8381f363de7",
+ "iv": b"9549e4ba69a61cad7856efc1",
+ "tag": b"d72da7f5c6cf0bca7242c71835809449",
+ "key": b"5c1155084cc0ede76b3bc22e9f7574ef",
+ "ct": b"f78b60ca125218493bea1c50a2e12ef4",
+ },
+ {
+ "aad": b"",
+ "pt": b"",
+ "iv": b"4e8df20faaf2c8eebe922902",
+ "tag": b"e39aeaebe86aa309a4d062d6274339",
+ "key": b"eac258e99c55e6ae8ef1da26640613d7",
+ "ct": b"",
+ },
+ {
+ "aad": b"",
+ "iv": b"55fef82cde693ce76efcc193",
+ "tag": b"3d68111a81ed22d2ef5bccac4fc27f",
+ "key": b"3726cf02fcc6b8639a5497652c94350d",
+ "ct": b"",
+ "fail": True,
+ },
+ {
+ "aad": b"",
+ "iv": b"eec51e7958c3f20a1bb71815",
+ "tag": b"a81886b3fb26e51fca87b267e1e157",
+ "key": b"f202299d5fd74f03b12d2119a6c4c038",
+ "ct": b"",
+ "fail": True,
+ },
+ {
+ "aad": b"",
+ "pt": b"",
+ "iv": b"f5cf3227444afd905a5f6dba",
+ "tag": b"1665b0f1a0b456e1664cfd3de08ccd",
+ "key": b"fd52925f39546b4c55ffb6b20c59898c",
+ "ct": b"",
+ },
+ {
+ "aad": b"",
+ "iv": b"3c",
+ "tag": b"eae841d4355feeb3f786bc86625f1e5b",
+ "key": b"58fab7632bcf10d2bcee58520bf37414",
+ "ct": b"15c4db4cbb451211179d57017f",
+ "fail": True,
+ },
]
def test_load_pkcs1_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
Test vectors for RSA-PSS
========================
@@ -789,168 +833,201 @@ def test_load_pkcs1_vectors():
# =============================================
# <snip>
- """).splitlines()
+ """
+ ).splitlines()
vectors = tuple(load_pkcs1_vectors(vector_data))
expected = (
(
{
- 'modulus': int(
- '495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f77'
- '8a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e58'
- '2de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218'
- 'f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a'
- '2b8efab0561b0810344739ada0733f', 16),
- 'public_exponent': int('10001', 16),
- 'private_exponent': int(
- '6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea'
- '9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7'
- '396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab'
- '54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701'
- 'c2d6266d517219ad0ec6d347dbe9', 16),
- 'p': int(
- '8dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab7'
- '2619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c'
- '8060645a1d29edb', 16),
- 'q': int(
- '847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b'
- '97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca41'
- '74825b48f49706d', 16),
- 'dmp1': int(
- '05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fc'
- 'e69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee1'
- '03deb771d105fd85', 16),
- 'dmq1': int(
- '04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b366'
- '9bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e3'
- '0a7e7d241551e1b9', 16),
- 'iqmp': int(
- '07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef53'
- '1b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7'
- 'b06e45307dc91f3f', 16),
- 'examples': [
+ "modulus": int(
+ "495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f77"
+ "8a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e58"
+ "2de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218"
+ "f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a"
+ "2b8efab0561b0810344739ada0733f",
+ 16,
+ ),
+ "public_exponent": int("10001", 16),
+ "private_exponent": int(
+ "6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea"
+ "9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7"
+ "396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab"
+ "54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701"
+ "c2d6266d517219ad0ec6d347dbe9",
+ 16,
+ ),
+ "p": int(
+ "8dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab7"
+ "2619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c"
+ "8060645a1d29edb",
+ 16,
+ ),
+ "q": int(
+ "847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b"
+ "97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca41"
+ "74825b48f49706d",
+ 16,
+ ),
+ "dmp1": int(
+ "05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fc"
+ "e69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee1"
+ "03deb771d105fd85",
+ 16,
+ ),
+ "dmq1": int(
+ "04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b366"
+ "9bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e3"
+ "0a7e7d241551e1b9",
+ 16,
+ ),
+ "iqmp": int(
+ "07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef53"
+ "1b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7"
+ "b06e45307dc91f3f",
+ 16,
+ ),
+ "examples": [
{
- 'message': b'81332f4be62948415ea1d899792eeacf6c6e1db1d'
- b'a8be13b5cea41db2fed467092e1ff398914c71425'
- b'9775f595f8547f735692a575e6923af78f22c6997'
- b'ddb90fb6f72d7bb0dd5744a31decd3dc368584983'
- b'6ed34aec596304ad11843c4f88489f209735f5fb7'
- b'fdaf7cec8addc5818168f880acbf490d51005b7a8'
- b'e84e43e54287977571dd99eea4b161eb2df1f5108'
- b'f12a4142a83322edb05a75487a3435c9a78ce53ed'
- b'93bc550857d7a9fb',
- 'salt': b'1d65491d79c864b373009be6f6f2467bac4c78fa',
- 'signature': b'0262ac254bfa77f3c1aca22c5179f8f040422b3'
- b'c5bafd40a8f21cf0fa5a667ccd5993d42dbafb4'
- b'09c520e25fce2b1ee1e716577f1efa17f3da280'
- b'52f40f0419b23106d7845aaf01125b698e7a4df'
- b'e92d3967bb00c4d0d35ba3552ab9a8b3eef07c7'
- b'fecdbc5424ac4db1e20cb37d0b2744769940ea9'
- b'07e17fbbca673b20522380c5'
- }, {
- 'message': b'e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3c'
- b'ede9d0faabf4fcc8e60a973e5595fd9ea08',
- 'salt': b'435c098aa9909eb2377f1248b091b68987ff1838',
- 'signature': b'2707b9ad5115c58c94e932e8ec0a280f56339e4'
- b'4a1b58d4ddcff2f312e5f34dcfe39e89c6a94dc'
- b'ee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6'
- b'c86ee68396e8b3a14c9c8f34b178eb741f9d3f1'
- b'21109bf5c8172fada2e768f9ea1433032c004a8'
- b'aa07eb990000a48dc94c8bac8aabe2b09b1aa46'
- b'c0a2aa0e12f63fbba775ba7e'
- }
- ]
+ "message": b"81332f4be62948415ea1d899792eeacf6c6e1db1d"
+ b"a8be13b5cea41db2fed467092e1ff398914c71425"
+ b"9775f595f8547f735692a575e6923af78f22c6997"
+ b"ddb90fb6f72d7bb0dd5744a31decd3dc368584983"
+ b"6ed34aec596304ad11843c4f88489f209735f5fb7"
+ b"fdaf7cec8addc5818168f880acbf490d51005b7a8"
+ b"e84e43e54287977571dd99eea4b161eb2df1f5108"
+ b"f12a4142a83322edb05a75487a3435c9a78ce53ed"
+ b"93bc550857d7a9fb",
+ "salt": b"1d65491d79c864b373009be6f6f2467bac4c78fa",
+ "signature": b"0262ac254bfa77f3c1aca22c5179f8f040422b3"
+ b"c5bafd40a8f21cf0fa5a667ccd5993d42dbafb4"
+ b"09c520e25fce2b1ee1e716577f1efa17f3da280"
+ b"52f40f0419b23106d7845aaf01125b698e7a4df"
+ b"e92d3967bb00c4d0d35ba3552ab9a8b3eef07c7"
+ b"fecdbc5424ac4db1e20cb37d0b2744769940ea9"
+ b"07e17fbbca673b20522380c5",
+ },
+ {
+ "message": b"e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3c"
+ b"ede9d0faabf4fcc8e60a973e5595fd9ea08",
+ "salt": b"435c098aa9909eb2377f1248b091b68987ff1838",
+ "signature": b"2707b9ad5115c58c94e932e8ec0a280f56339e4"
+ b"4a1b58d4ddcff2f312e5f34dcfe39e89c6a94dc"
+ b"ee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6"
+ b"c86ee68396e8b3a14c9c8f34b178eb741f9d3f1"
+ b"21109bf5c8172fada2e768f9ea1433032c004a8"
+ b"aa07eb990000a48dc94c8bac8aabe2b09b1aa46"
+ b"c0a2aa0e12f63fbba775ba7e",
+ },
+ ],
},
-
{
- 'modulus': int(
- '495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f77'
- '8a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e58'
- '2de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218'
- 'f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a'
- '2b8efab0561b0810344739ada0733f', 16),
- 'public_exponent': int('10001', 16)
- }
+ "modulus": int(
+ "495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f77"
+ "8a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e58"
+ "2de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218"
+ "f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a"
+ "2b8efab0561b0810344739ada0733f",
+ 16,
+ ),
+ "public_exponent": int("10001", 16),
+ },
),
(
{
- 'modulus': int(
- 'e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd0'
- '6c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee31'
- '5ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b'
- '1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddb'
- 'c2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8d'
- 'e3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6f'
- 'd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b', 16),
- 'public_exponent': int('10001', 16),
- 'private_exponent': int(
- '6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da'
- '6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d514'
- '10b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4'
- 'd96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf2131166'
- '6070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f'
- '82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab32'
- '8ce420689903c00c7b5fd31b75503a6d419684d629', 16),
- 'p': int(
- 'f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac'
- '086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a'
- '82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f61'
- '54a762aed165d47dee367', 16),
- 'q': int(
- 'ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f'
- '288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e472'
- '8cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b48'
- '9c176128092d629e49d3d', 16),
- 'dmp1': int(
- '2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e'
- '39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0a'
- 'b556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec9'
- '93e9353e480d9eec6289f', 16),
- 'dmq1': int(
- '4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4'
- 'ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec'
- '56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56e'
- 'e4dba42c5fdb61aec2669', 16),
- 'iqmp': int(
- '77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8'
- '512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124c'
- 'bbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65'
- '757bb3f857a58dce52156', 16),
- 'examples': [
+ "modulus": int(
+ "e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd0"
+ "6c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee31"
+ "5ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b"
+ "1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddb"
+ "c2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8d"
+ "e3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6f"
+ "d4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b",
+ 16,
+ ),
+ "public_exponent": int("10001", 16),
+ "private_exponent": int(
+ "6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da"
+ "6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d514"
+ "10b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4"
+ "d96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf2131166"
+ "6070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f"
+ "82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab32"
+ "8ce420689903c00c7b5fd31b75503a6d419684d629",
+ 16,
+ ),
+ "p": int(
+ "f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac"
+ "086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a"
+ "82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f61"
+ "54a762aed165d47dee367",
+ 16,
+ ),
+ "q": int(
+ "ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f"
+ "288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e472"
+ "8cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b48"
+ "9c176128092d629e49d3d",
+ 16,
+ ),
+ "dmp1": int(
+ "2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e"
+ "39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0a"
+ "b556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec9"
+ "93e9353e480d9eec6289f",
+ 16,
+ ),
+ "dmq1": int(
+ "4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4"
+ "ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec"
+ "56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56e"
+ "e4dba42c5fdb61aec2669",
+ 16,
+ ),
+ "iqmp": int(
+ "77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8"
+ "512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124c"
+ "bbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65"
+ "757bb3f857a58dce52156",
+ 16,
+ ),
+ "examples": [
{
- 'message': b'06add75ab689de067744e69a2ebd4b90fa9383003'
- b'cd05ff536cbf294cd215f0923b7fc9004f0aa1852'
- b'71a1d0061fd0e9777ad1ec0c71591f578bf7b8e5a'
- b'1',
- 'signature': b'4514210e541d5bad7dd60ae549b943acc44f213'
- b'90df5b61318455a17610df5b74d84aed232f17e'
- b'59d91dd2659922f812dbd49681690384b954e9a'
- b'dfb9b1a968c0cbff763eceed62750c59164b5e0'
- b'80a8fef3d55bfe2acfad2752a6a8459fa1fab49'
- b'ad378c6964b23ee97fd1034610c5cc14c61e0eb'
- b'fb1711f8ade96fe6557b38'
+ "message": b"06add75ab689de067744e69a2ebd4b90fa9383003"
+ b"cd05ff536cbf294cd215f0923b7fc9004f0aa1852"
+ b"71a1d0061fd0e9777ad1ec0c71591f578bf7b8e5a"
+ b"1",
+ "signature": b"4514210e541d5bad7dd60ae549b943acc44f213"
+ b"90df5b61318455a17610df5b74d84aed232f17e"
+ b"59d91dd2659922f812dbd49681690384b954e9a"
+ b"dfb9b1a968c0cbff763eceed62750c59164b5e0"
+ b"80a8fef3d55bfe2acfad2752a6a8459fa1fab49"
+ b"ad378c6964b23ee97fd1034610c5cc14c61e0eb"
+ b"fb1711f8ade96fe6557b38",
}
- ]
+ ],
},
-
{
- 'modulus': int(
- 'e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd0'
- '6c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee31'
- '5ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b'
- '1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddb'
- 'c2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8d'
- 'e3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6f'
- 'd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b', 16),
- 'public_exponent': int('10001', 16)
- }
- )
+ "modulus": int(
+ "e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd0"
+ "6c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee31"
+ "5ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b"
+ "1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddb"
+ "c2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8d"
+ "e3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6f"
+ "d4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b",
+ 16,
+ ),
+ "public_exponent": int("10001", 16),
+ },
+ ),
)
assert vectors == expected
def test_load_pkcs1_oaep_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
Test vectors for RSA-OAEP
=========================
@@ -1083,88 +1160,106 @@ def test_load_pkcs1_oaep_vectors():
15 91 2d f6 96 ff e0 70 29 32 94 6d 71 49 2b 44
# =============================================
- """).splitlines()
+ """
+ ).splitlines()
vectors = load_pkcs1_vectors(vector_data)
expected = [
(
{
- 'modulus': int(
- 'a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae481'
- '1a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6'
- 'c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb'
- '662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616'
- 'd4f5ba10d4cfd226de88d39f16fb', 16),
- 'public_exponent': int('10001', 16),
- 'private_exponent': int(
- '53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4'
- 'f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b'
- '8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3'
- 'd3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d'
- '0cf539e9cfcdd3de653729ead5d1', 16),
- 'p': int(
- 'd32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9'
- 'cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dc'
- 'ad212eac7ca39d', 16),
- 'q': int(
- 'cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3'
- 'd5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030'
- 'e860b0288b5d77', 16),
- 'dmp1': int(
- '0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f27'
- '41fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e403796'
- '8db37878e695c1', 16),
- 'dmq1': int(
- '95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771'
- 'ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5'
- 'f112ca85d71583', 16),
- 'iqmp': int(
- '4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a'
- '63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a'
- '8ca1d2f4fbd8e1', 16),
- 'examples': [
+ "modulus": int(
+ "a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae481"
+ "1a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6"
+ "c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb"
+ "662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616"
+ "d4f5ba10d4cfd226de88d39f16fb",
+ 16,
+ ),
+ "public_exponent": int("10001", 16),
+ "private_exponent": int(
+ "53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4"
+ "f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b"
+ "8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3"
+ "d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d"
+ "0cf539e9cfcdd3de653729ead5d1",
+ 16,
+ ),
+ "p": int(
+ "d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9"
+ "cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dc"
+ "ad212eac7ca39d",
+ 16,
+ ),
+ "q": int(
+ "cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3"
+ "d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030"
+ "e860b0288b5d77",
+ 16,
+ ),
+ "dmp1": int(
+ "0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f27"
+ "41fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e403796"
+ "8db37878e695c1",
+ 16,
+ ),
+ "dmq1": int(
+ "95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771"
+ "ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5"
+ "f112ca85d71583",
+ 16,
+ ),
+ "iqmp": int(
+ "4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a"
+ "63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a"
+ "8ca1d2f4fbd8e1",
+ 16,
+ ),
+ "examples": [
{
- 'message': b'6628194e12073db03ba94cda9ef9532397d50dba7'
- b'9b987004afefe34',
- 'seed': b'18b776ea21069d69776a33e96bad48e1dda0a5ef',
- 'encryption': b'354fe67b4a126d5d35fe36c777791a3f7ba13d'
- b'ef484e2d3908aff722fad468fb21696de95d0b'
- b'e911c2d3174f8afcc201035f7b6d8e69402de5'
- b'451618c21a535fa9d7bfc5b8dd9fc243f8cf92'
- b'7db31322d6e881eaa91a996170e657a05a2664'
- b'26d98c88003f8477c1227094a0d9fa1e8c4024'
- b'309ce1ecccb5210035d47ac72e8a'
- }, {
- 'message': b'750c4047f547e8e41411856523298ac9bae245efa'
- b'f1397fbe56f9dd5',
- 'seed': b'0cc742ce4a9b7f32f951bcb251efd925fe4fe35f',
- 'encryption': b'640db1acc58e0568fe5407e5f9b701dff8c3c9'
- b'1e716c536fc7fcec6cb5b71c1165988d4a279e'
- b'1577d730fc7a29932e3f00c81515236d8d8e31'
- b'017a7a09df4352d904cdeb79aa583adcc31ea6'
- b'98a4c05283daba9089be5491f67c1a4ee48dc7'
- b'4bbbe6643aef846679b4cb395a352d5ed11591'
- b'2df696ffe0702932946d71492b44'
- }
- ]
+ "message": b"6628194e12073db03ba94cda9ef9532397d50dba7"
+ b"9b987004afefe34",
+ "seed": b"18b776ea21069d69776a33e96bad48e1dda0a5ef",
+ "encryption": b"354fe67b4a126d5d35fe36c777791a3f7ba13d"
+ b"ef484e2d3908aff722fad468fb21696de95d0b"
+ b"e911c2d3174f8afcc201035f7b6d8e69402de5"
+ b"451618c21a535fa9d7bfc5b8dd9fc243f8cf92"
+ b"7db31322d6e881eaa91a996170e657a05a2664"
+ b"26d98c88003f8477c1227094a0d9fa1e8c4024"
+ b"309ce1ecccb5210035d47ac72e8a",
+ },
+ {
+ "message": b"750c4047f547e8e41411856523298ac9bae245efa"
+ b"f1397fbe56f9dd5",
+ "seed": b"0cc742ce4a9b7f32f951bcb251efd925fe4fe35f",
+ "encryption": b"640db1acc58e0568fe5407e5f9b701dff8c3c9"
+ b"1e716c536fc7fcec6cb5b71c1165988d4a279e"
+ b"1577d730fc7a29932e3f00c81515236d8d8e31"
+ b"017a7a09df4352d904cdeb79aa583adcc31ea6"
+ b"98a4c05283daba9089be5491f67c1a4ee48dc7"
+ b"4bbbe6643aef846679b4cb395a352d5ed11591"
+ b"2df696ffe0702932946d71492b44",
+ },
+ ],
},
-
{
- 'modulus': int(
- 'a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae481'
- '1a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6'
- 'c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb'
- '662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616'
- 'd4f5ba10d4cfd226de88d39f16fb', 16),
- 'public_exponent': int('10001', 16),
- }
+ "modulus": int(
+ "a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae481"
+ "1a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6"
+ "c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb"
+ "662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616"
+ "d4f5ba10d4cfd226de88d39f16fb",
+ 16,
+ ),
+ "public_exponent": int("10001", 16),
+ },
)
]
assert vectors == expected
def test_load_hotp_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# HOTP Test Vectors
# RFC 4226 Appendix D
@@ -1197,7 +1292,8 @@ def test_load_hotp_vectors():
TRUNCATED = 66ef7655
HOTP = 969429
SECRET = 12345678901234567890
- """).splitlines()
+ """
+ ).splitlines()
assert load_nist_vectors(vector_data) == [
{
@@ -1232,7 +1328,8 @@ def test_load_hotp_vectors():
def test_load_totp_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# TOTP Test Vectors
# RFC 6238 Appendix B
@@ -1253,7 +1350,8 @@ def test_load_totp_vectors():
TOTP = 90693936
MODE = SHA512
SECRET = 12345678901234567890
- """).splitlines()
+ """
+ ).splitlines()
assert load_nist_vectors(vector_data) == [
{
@@ -1278,7 +1376,8 @@ def test_load_totp_vectors():
def test_load_rsa_nist_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.4
# "SigGen PKCS#1 RSASSA-PSS" information
# Mod sizes selected: 1024 1536 2048 3072 4096
@@ -1307,33 +1406,40 @@ def test_load_rsa_nist_vectors():
SHAAlg = SHA512
Msg = 3456781293fab829
S = deadbeef0000
- """).splitlines()
+ """
+ ).splitlines()
vectors = load_rsa_nist_vectors(vector_data)
assert vectors == [
{
- "modulus": int("bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda"
- "707a146b3b4e29989d", 16),
+ "modulus": int(
+ "bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda"
+ "707a146b3b4e29989d",
+ 16,
+ ),
"public_exponent": 65537,
"algorithm": "SHA1",
"salt_length": 20,
"msg": b"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc6"
- b"11714f14e",
+ b"11714f14e",
"s": b"682cf53c1145d22a50caa9eb1a9ba70670c5915e0fdfde6457a765de2a8"
- b"fe12de97",
- "fail": False
+ b"fe12de97",
+ "fail": False,
},
{
- "modulus": int("bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda"
- "707a146b3b4e29989d", 16),
+ "modulus": int(
+ "bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda"
+ "707a146b3b4e29989d",
+ 16,
+ ),
"public_exponent": 65537,
"algorithm": "SHA384",
"salt_length": 20,
"msg": b"e511903c2f1bfba245467295ac95413ac4746c984c3750a728c388aa6"
- b"28b0ebf",
+ b"28b0ebf",
"s": b"9c748702bbcc1f9468864cd360c8c39d007b2d8aaee833606c70f7593cf"
- b"0d1519",
- "fail": False
+ b"0d1519",
+ "fail": False,
},
{
"modulus": 78187493520,
@@ -1342,13 +1448,14 @@ def test_load_rsa_nist_vectors():
"salt_length": 20,
"msg": b"3456781293fab829",
"s": b"deadbeef0000",
- "fail": False
+ "fail": False,
},
]
def test_load_rsa_nist_pkcs1v15_verification_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.0
# "SigVer PKCS#1 Ver 1.5" information
# Mod sizes selected: 1024 1536 2048 3072 4096
@@ -1377,50 +1484,73 @@ def test_load_rsa_nist_pkcs1v15_verification_vectors():
S = 2b91c6ae2b3c46ff18d5b7abe239634cb752d0acb53eea0ccd8ea8483036a50e8faf
SaltVal = 11223344555432167890
Result = P
- """).splitlines()
+ """
+ ).splitlines()
vectors = load_rsa_nist_vectors(vector_data)
assert vectors == [
{
- "modulus": int("be499b5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b"
- "9bfeb7aa72db126411", 16),
- "p": int("e7a80c5d211c06acb900939495f26d365fc2b4825b75e356f89003ea"
- "a5931e6be5c3", 16),
- "q": int("d248aa248000f720258742da67b711940c8f76e1ecd52b67a6ffe1e4"
- "9354d66ff84f", 16),
+ "modulus": int(
+ "be499b5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b"
+ "9bfeb7aa72db126411",
+ 16,
+ ),
+ "p": int(
+ "e7a80c5d211c06acb900939495f26d365fc2b4825b75e356f89003ea"
+ "a5931e6be5c3",
+ 16,
+ ),
+ "q": int(
+ "d248aa248000f720258742da67b711940c8f76e1ecd52b67a6ffe1e4"
+ "9354d66ff84f",
+ 16,
+ ),
"public_exponent": 17,
"algorithm": "SHA1",
- "private_exponent": int("0d0f17362bdad181db4e1fe03e8de1a3208989914"
- "e14bf269558826bfa20faf4b68d", 16),
+ "private_exponent": int(
+ "0d0f17362bdad181db4e1fe03e8de1a3208989914"
+ "e14bf269558826bfa20faf4b68d",
+ 16,
+ ),
"msg": b"6b9cfac0ba1c7890b13e381ce752195cc1375237db2afcf6a9dcd1f95"
- b"ec733a80c",
+ b"ec733a80c",
"s": b"562d87b5781c01d166fef3972669a0495c145b898a17df4743fbefb0a15"
- b"82bd6ba9d",
+ b"82bd6ba9d",
"saltval": b"11223344555432167890",
- "fail": True
+ "fail": True,
},
{
- "modulus": int("be499b5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b"
- "9bfeb7aa72db126411", 16),
- "p": int("e7a80c5d211c06acb900939495f26d365fc2b4825b75e356f89003ea"
- "a5931e6be5c3", 16),
- "q": int("d248aa248000f720258742da67b711940c8f76e1ecd52b67a6ffe1e4"
- "9354d66ff84f", 16),
+ "modulus": int(
+ "be499b5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b"
+ "9bfeb7aa72db126411",
+ 16,
+ ),
+ "p": int(
+ "e7a80c5d211c06acb900939495f26d365fc2b4825b75e356f89003ea"
+ "a5931e6be5c3",
+ 16,
+ ),
+ "q": int(
+ "d248aa248000f720258742da67b711940c8f76e1ecd52b67a6ffe1e4"
+ "9354d66ff84f",
+ 16,
+ ),
"public_exponent": 3,
"algorithm": "SHA1",
"private_exponent": int("bfa20faf4b68d", 16),
"msg": b"2a67c70ff14f9b34ddb42e6f89d5971057a0da980fc9ae70c81a84da0"
- b"c0ac42737",
+ b"c0ac42737",
"s": b"2b91c6ae2b3c46ff18d5b7abe239634cb752d0acb53eea0ccd8ea848303"
- b"6a50e8faf",
+ b"6a50e8faf",
"saltval": b"11223344555432167890",
- "fail": False
+ "fail": False,
},
]
def test_load_rsa_nist_pss_verification_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.0
# "SigVer PKCS#1 RSASSA-PSS" information
# Mod sizes selected: 1024 1536 2048 3072 4096
@@ -1450,7 +1580,8 @@ def test_load_rsa_nist_pss_verification_vectors():
S = 2b91c6ae2b3c46ff18d5b7abe239634cb7
SaltVal = 11223344555432167890
Result = P
- """).splitlines()
+ """
+ ).splitlines()
vectors = load_rsa_nist_vectors(vector_data)
assert vectors == [
@@ -1465,7 +1596,7 @@ def test_load_rsa_nist_pss_verification_vectors():
"s": b"562d87b5781c01d166fef3972669a0495c",
"saltval": b"11223344555432167890",
"salt_length": 10,
- "fail": True
+ "fail": True,
},
{
"modulus": int("be499b5e7f06c83fa0293e31465c8eb6b5", 16),
@@ -1478,13 +1609,14 @@ def test_load_rsa_nist_pss_verification_vectors():
"s": b"2b91c6ae2b3c46ff18d5b7abe239634cb7",
"saltval": b"11223344555432167890",
"salt_length": 10,
- "fail": False
+ "fail": False,
},
]
def test_load_fips_dsa_key_pair_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.1
# "KeyPair" information
# Mod sizes selected: L=1024, N=160:: L=2048, N=224 :: L=2048, N=256 :: L
@@ -1599,213 +1731,303 @@ de61329a78d526f65245380ce877e979c5b50de66c9c30d66382c8f254653d25a1eb1d3a4897d7\
623399b473ce712a2184cf2da1861706c41466806aefe41b497db82aca6c31c8f4aa68c17d1d9e\
380b57998917655783ec96e5234a131f7299398d36f1f5f84297a55ff292f1f060958c358fed34\
6db2de45127ca728a9417b2c54203e33e53b9a061d924395b09afab8daf3e8dd7eedcec3ac
- """).splitlines()
+ """
+ ).splitlines()
expected = [
- {'g': int('06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce499'
- '1d2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d3000'
- '42bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34cd12'
- '615474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f'
- '4fd9f93cd6f4f17fc076341a7e7d9', 16),
- 'p': int('d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725e'
- 'f341eabb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae791210'
- '2b6b502e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189c'
- 'ef1ace778d7845a5c1c1c7147123188f8dc551054ee162b634d60f097f7'
- '19076640e20980a0093113a8bd73', 16),
- 'q': int('96c5390a8b612c0e422bb2b0ea194a3ec935a281', 16),
- 'x': int('8185fee9cc7c0e91fd85503274f1cd5a3fd15a49', 16),
- 'y': int('6f26d98d41de7d871b6381851c9d91fa03942092ab6097e76422'
- '070edb71db44ff568280fdb1709f8fc3feab39f1f824adaeb2a29808815'
- '6ac31af1aa04bf54f475bdcfdcf2f8a2dd973e922d83e76f01655861760'
- '3129b21c70bf7d0e5dc9e68fe332e295b65876eb9a12fe6fca9f1a1ce80'
- '204646bf99b5771d249a6fea627', 16)},
- {'g': int('06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce4991d'
- '2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d30004'
- '2bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34cd126'
- '15474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f4fd9'
- 'f93cd6f4f17fc076341a7e7d9', 16),
- 'p': int('d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef341e'
- 'abb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae7912102b6b50'
- '2e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189cef1a'
- 'ce778d7845a5c1c1c7147123188f8dc551054ee162b634d6'
- '0f097f719076640e20980a0093113a8bd73', 16),
- 'q': int('96c5390a8b612c0e422bb2b0ea194a3ec935a281', 16),
- 'x': int('85322d6ea73083064376099ca2f65f56e8522d9b', 16),
- 'y': int('21f8690f717c9f4dcb8f4b6971de2f15b9231fcf41b7eeb997d781f240'
- 'bfdddfd2090d22083c26cca39bf37c9caf1ec89518ea64845a50d747b49'
- '131ffff6a2fd11ea7bacbb93c7d05137383a06365af82225dd3713c'
- 'a5a45006316f53bd12b0e260d5f79795e5a4c9f353f12867a1d3'
- '202394673ada8563b71555e53f415254', 16)},
-
- {'g': int('e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b191'
- '3413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9807'
- '6739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908bae0'
- '3e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d5551b2'
- 'fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c61568f78'
- 'd0706b10a26f23b4f197c322b825002284a0aca91807bba98ece912'
- 'b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f8403873d'
- '12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed273b1'
- '46ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302', 16),
- 'p': int('ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace'
- '5e9c41434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17d'
- 'ac62c98e706af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b122'
- '52c40278fff9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d2'
- '44e54561b0dca39b301de8c49da9fb23df33c6182e3f983208c560fb5'
- '119fbf78ebe3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a'
- '2b4f0e9e3d9dbac122f750dd754325135257488b1f6ecabf21bff2947'
- 'fe0d3b2cb7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a'
- '908c36e95e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac'
- '5aa66ef7', 16),
- 'q': int('8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b1'
- '8f507192c19d', 16),
- 'x': int('405772da6e90d809e77d5de796562a2dd4dfd10ef00a83a3aba6'
- 'bd818a0348a1', 16),
- 'y': int('6b32e31ab9031dc4dd0b5039a78d07826687ab087ae6de4736f5'
- 'b0434e1253092e8a0b231f9c87f3fc8a4cb5634eb194bf1b638'
- 'b7a7889620ce6711567e36aa36cda4604cfaa601a45918371d'
- '4ccf68d8b10a50a0460eb1dc0fff62ef5e6ee4d473e18ea4a6'
- '6c196fb7e677a49b48241a0b4a97128eff30fa437050501a584'
- 'f8771e7280d26d5af30784039159c11ebfea10b692fd0a58215ee'
- 'b18bff117e13f08db792ed4151a218e4bed8dddfb0793225bd1e97'
- '73505166f4bd8cedbb286ea28232972da7bae836ba97329ba6b0a36508'
- 'e50a52a7675e476d4d4137eae13f22a9d2fefde708ba8f34bf336c6e7'
- '6331761e4b0617633fe7ec3f23672fb19d27', 16)},
- {'g': int('e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b191'
- '3413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9807'
- '6739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908bae0'
- '3e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d5551b2'
- 'fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c61568f78'
- 'd0706b10a26f23b4f197c322b825002284a0aca91807bba98ece912'
- 'b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f8403873d'
- '12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed273b1'
- '46ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302', 16),
- 'p': int('ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace'
- '5e9c41434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17d'
- 'ac62c98e706af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b122'
- '52c40278fff9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d2'
- '44e54561b0dca39b301de8c49da9fb23df33c6182e3f983208c560fb5'
- '119fbf78ebe3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a'
- '2b4f0e9e3d9dbac122f750dd754325135257488b1f6ecabf21bff2947'
- 'fe0d3b2cb7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a'
- '908c36e95e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac'
- '5aa66ef7', 16),
- 'q': int('8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b1'
- '8f507192c19d', 16),
- 'x': int('0e0b95e31fda3f888059c46c3002ef8f2d6be112d0209aeb9e95'
- '45da67aeea80', 16),
- 'y': int('778082b77ddba6f56597cc74c3a612abf2ddbd85cc81430c99ab'
- '843c1f630b9db0139965f563978164f9bf3a8397256be714625'
- 'cd41cd7fa0067d94ea66d7e073f7125af692ad01371d4a17f45'
- '50590378f2b074030c20e36911598a1018772f61be3b24de4be'
- '5a388ccc09e15a92819c31dec50de9fde105b49eaa097b9d13d'
- '9219eeb33b628facfd1c78a7159c8430d0647c506e7e3de74763c'
- 'b351eada72c00bef3c9641881e6254870c1e6599f8ca2f1bbb74f'
- '39a905e3a34e4544168e6e50c9e3305fd09cab6ed4aff6fda6e0d'
- '5bf375c81ac9054406d9193b003c89272f1bd83d48250134b65c77'
- 'c2b6332d38d34d9016f0e8975536ad6c348a1faedb0', 16)},
-
- {'g': int('ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978d'
- 'b2104d7394b493c18332c64cec906a71c3778bd93341165dee8'
- 'e6cd4ca6f13afff531191194ada55ecf01ff94d6cf7c4768b82'
- 'dd29cd131aaf202aefd40e564375285c01f3220af4d70b96f1'
- '395420d778228f1461f5d0b8e47357e87b1fe3286223b553e3'
- 'fc9928f16ae3067ded6721bedf1d1a01bfd22b9ae85fce77820d88cdf'
- '50a6bde20668ad77a707d1c60fcc5d51c9de488610d0285eb8ff721f'
- 'f141f93a9fb23c1d1f7654c07c46e58836d1652828f71057b8aff0b077'
- '8ef2ca934ea9d0f37daddade2d823a4d8e362721082e279d003b575ee'
- '59fd050d105dfd71cd63154efe431a0869178d9811f4f231dc5dcf3b'
- '0ec0f2b0f9896c32ec6c7ee7d60aa97109e09224907328d4e6acd1011'
- '7e45774406c4c947da8020649c3168f690e0bd6e91ac67074d1d436b'
- '58ae374523deaf6c93c1e6920db4a080b744804bb073cecfe83fa939'
- '8cf150afa286dc7eb7949750cf5001ce104e9187f7e16859afa8fd0d'
- '775ae', 16),
- 'p': int('f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d5828'
- 'c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a842'
- 'ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e8'
- '0abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84ec'
- '389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea2651'
- 'b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a1428'
- '5a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab0605'
- '48de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba9'
- '844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1d'
- '54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818f'
- '06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673a'
- 'e4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f7476'
- 'cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c11'
- '36f303f4b4d25ad5b692229957', 16),
- 'q': int('d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210'
- 'f6169041653b', 16),
- 'x': int('b2764c46113983777d3e7e97589f1303806d14ad9f2f1ef03309'
- '7de954b17706', 16),
- 'y': int('814824e435e1e6f38daa239aad6dad21033afce6a3ebd35c1359348a0f2'
- '418871968c2babfc2baf47742148828f8612183178f126504da73566b6'
- 'bab33ba1f124c15aa461555c2451d86c94ee21c3e3fc24c55527e'
- '01b1f03adcdd8ec5cb08082803a7b6a829c3e99eeb332a2cf5c035b0c'
- 'e0078d3d414d31fa47e9726be2989b8d06da2e6cd363f5a7d1515e3f4'
- '925e0b32adeae3025cc5a996f6fd27494ea408763de48f3bb39f6a06'
- '514b019899b312ec570851637b8865cff3a52bf5d54ad5a19e6e400'
- 'a2d33251055d0a440b50d53f4791391dc754ad02b9eab74c46b4903'
- 'f9d76f824339914db108057af7cde657d41766a99991ac8787694f'
- '4185d6f91d7627048f827b405ec67bf2fe56141c4c581d8c317333'
- '624e073e5879a82437cb0c7b435c0ce434e15965db1315d648959'
- '91e6bbe7dac040c42052408bbc53423fd31098248a58f8a67da3a'
- '39895cd0cc927515d044c1e3cb6a3259c3d0da354cce89ea3552c'
- '59609db10ee989986527436af21d9485ddf25f90f7dff6d2bae', 16)},
- {'g': int('ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978d'
- 'b2104d7394b493c18332c64cec906a71c3778bd93341165dee8'
- 'e6cd4ca6f13afff531191194ada55ecf01ff94d6cf7c4768b82'
- 'dd29cd131aaf202aefd40e564375285c01f3220af4d70b96f1'
- '395420d778228f1461f5d0b8e47357e87b1fe3286223b553e3'
- 'fc9928f16ae3067ded6721bedf1d1a01bfd22b9ae85fce77820d88cdf'
- '50a6bde20668ad77a707d1c60fcc5d51c9de488610d0285eb8ff721f'
- 'f141f93a9fb23c1d1f7654c07c46e58836d1652828f71057b8aff0b077'
- '8ef2ca934ea9d0f37daddade2d823a4d8e362721082e279d003b575ee'
- '59fd050d105dfd71cd63154efe431a0869178d9811f4f231dc5dcf3b'
- '0ec0f2b0f9896c32ec6c7ee7d60aa97109e09224907328d4e6acd1011'
- '7e45774406c4c947da8020649c3168f690e0bd6e91ac67074d1d436b'
- '58ae374523deaf6c93c1e6920db4a080b744804bb073cecfe83fa939'
- '8cf150afa286dc7eb7949750cf5001ce104e9187f7e16859afa8fd0d'
- '775ae', 16),
- 'p': int('f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d5828'
- 'c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a842'
- 'ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e8'
- '0abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84ec'
- '389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea2651'
- 'b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a1428'
- '5a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab0605'
- '48de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba9'
- '844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1d'
- '54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818f'
- '06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673a'
- 'e4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f7476'
- 'cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c11'
- '36f303f4b4d25ad5b692229957', 16),
- 'q': int('d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210'
- 'f6169041653b', 16),
- 'x': int('52e3e040efb30e1befd909a0bdbcfd140d005b1bff094af97186'
- '080262f1904d', 16),
- 'y': int('a5ae6e8f9b7a68ab0516dad4d7b7d002126f811d5a52e3d35c6d'
- '387fcb43fd19bf7792362f9c98f8348aa058bb62376685f3d0c3'
- '66c520d697fcd8416947151d4bbb6f32b53528a016479e99d2cd'
- '48d1fc679027c15f0042f207984efe05c1796bca8eba678dfdd0'
- '0b80418e3ea840557e73b09e003882f9a68edba3431d351d1ca0'
- '7a8150b018fdbdf6c2f1ab475792a3ccaa6594472a45f8dc777b'
- '60bf67de3e0f65c20d11b7d59faedf83fbce52617f500d9e5149'
- '47c455274c6e900464767fb56599b81344cf6d12c25cb2b7d038'
- 'd7b166b6cf30534811c15d0e8ab880a2ac06786ae2ddde61329a'
- '78d526f65245380ce877e979c5b50de66c9c30d66382c8f25465'
- '3d25a1eb1d3a4897d7623399b473ce712a2184cf2da1861706c4'
- '1466806aefe41b497db82aca6c31c8f4aa68c17d1d9e380b5799'
- '8917655783ec96e5234a131f7299398d36f1f5f84297a55ff292'
- 'f1f060958c358fed346db2de45127ca728a9417b2c54203e33e5'
- '3b9a061d924395b09afab8daf3e8dd7eedcec3ac', 16)}
+ {
+ "g": int(
+ "06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce499"
+ "1d2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d3000"
+ "42bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34cd12"
+ "615474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f"
+ "4fd9f93cd6f4f17fc076341a7e7d9",
+ 16,
+ ),
+ "p": int(
+ "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725e"
+ "f341eabb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae791210"
+ "2b6b502e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189c"
+ "ef1ace778d7845a5c1c1c7147123188f8dc551054ee162b634d60f097f7"
+ "19076640e20980a0093113a8bd73",
+ 16,
+ ),
+ "q": int("96c5390a8b612c0e422bb2b0ea194a3ec935a281", 16),
+ "x": int("8185fee9cc7c0e91fd85503274f1cd5a3fd15a49", 16),
+ "y": int(
+ "6f26d98d41de7d871b6381851c9d91fa03942092ab6097e76422"
+ "070edb71db44ff568280fdb1709f8fc3feab39f1f824adaeb2a29808815"
+ "6ac31af1aa04bf54f475bdcfdcf2f8a2dd973e922d83e76f01655861760"
+ "3129b21c70bf7d0e5dc9e68fe332e295b65876eb9a12fe6fca9f1a1ce80"
+ "204646bf99b5771d249a6fea627",
+ 16,
+ ),
+ },
+ {
+ "g": int(
+ "06b7861abbd35cc89e79c52f68d20875389b127361ca66822138ce4991d"
+ "2b862259d6b4548a6495b195aa0e0b6137ca37eb23b94074d3c3d30004"
+ "2bdf15762812b6333ef7b07ceba78607610fcc9ee68491dbc1e34cd126"
+ "15474e52b18bc934fb00c61d39e7da8902291c4434a4e2224c3f4fd9"
+ "f93cd6f4f17fc076341a7e7d9",
+ 16,
+ ),
+ "p": int(
+ "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d4b725ef341e"
+ "abb47cf8a7a8a41e792a156b7ce97206c4f9c5ce6fc5ae7912102b6b50"
+ "2e59050b5b21ce263dddb2044b652236f4d42ab4b5d6aa73189cef1a"
+ "ce778d7845a5c1c1c7147123188f8dc551054ee162b634d6"
+ "0f097f719076640e20980a0093113a8bd73",
+ 16,
+ ),
+ "q": int("96c5390a8b612c0e422bb2b0ea194a3ec935a281", 16),
+ "x": int("85322d6ea73083064376099ca2f65f56e8522d9b", 16),
+ "y": int(
+ "21f8690f717c9f4dcb8f4b6971de2f15b9231fcf41b7eeb997d781f240"
+ "bfdddfd2090d22083c26cca39bf37c9caf1ec89518ea64845a50d747b49"
+ "131ffff6a2fd11ea7bacbb93c7d05137383a06365af82225dd3713c"
+ "a5a45006316f53bd12b0e260d5f79795e5a4c9f353f12867a1d3"
+ "202394673ada8563b71555e53f415254",
+ 16,
+ ),
+ },
+ {
+ "g": int(
+ "e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b191"
+ "3413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9807"
+ "6739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908bae0"
+ "3e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d5551b2"
+ "fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c61568f78"
+ "d0706b10a26f23b4f197c322b825002284a0aca91807bba98ece912"
+ "b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f8403873d"
+ "12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed273b1"
+ "46ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302",
+ 16,
+ ),
+ "p": int(
+ "ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace"
+ "5e9c41434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17d"
+ "ac62c98e706af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b122"
+ "52c40278fff9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d2"
+ "44e54561b0dca39b301de8c49da9fb23df33c6182e3f983208c560fb5"
+ "119fbf78ebe3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a"
+ "2b4f0e9e3d9dbac122f750dd754325135257488b1f6ecabf21bff2947"
+ "fe0d3b2cb7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a"
+ "908c36e95e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac"
+ "5aa66ef7",
+ 16,
+ ),
+ "q": int(
+ "8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b1"
+ "8f507192c19d",
+ 16,
+ ),
+ "x": int(
+ "405772da6e90d809e77d5de796562a2dd4dfd10ef00a83a3aba6"
+ "bd818a0348a1",
+ 16,
+ ),
+ "y": int(
+ "6b32e31ab9031dc4dd0b5039a78d07826687ab087ae6de4736f5"
+ "b0434e1253092e8a0b231f9c87f3fc8a4cb5634eb194bf1b638"
+ "b7a7889620ce6711567e36aa36cda4604cfaa601a45918371d"
+ "4ccf68d8b10a50a0460eb1dc0fff62ef5e6ee4d473e18ea4a6"
+ "6c196fb7e677a49b48241a0b4a97128eff30fa437050501a584"
+ "f8771e7280d26d5af30784039159c11ebfea10b692fd0a58215ee"
+ "b18bff117e13f08db792ed4151a218e4bed8dddfb0793225bd1e97"
+ "73505166f4bd8cedbb286ea28232972da7bae836ba97329ba6b0a36508"
+ "e50a52a7675e476d4d4137eae13f22a9d2fefde708ba8f34bf336c6e7"
+ "6331761e4b0617633fe7ec3f23672fb19d27",
+ 16,
+ ),
+ },
+ {
+ "g": int(
+ "e4c4eca88415b23ecf811c96e48cd24200fe916631a68a684e6ccb6b191"
+ "3413d344d1d8d84a333839d88eee431521f6e357c16e6a93be111a9807"
+ "6739cd401bab3b9d565bf4fb99e9d185b1e14d61c93700133f908bae0"
+ "3e28764d107dcd2ea7674217622074bb19efff482f5f5c1a86d5551b2"
+ "fc68d1c6e9d8011958ef4b9c2a3a55d0d3c882e6ad7f9f0f3c61568f78"
+ "d0706b10a26f23b4f197c322b825002284a0aca91807bba98ece912"
+ "b80e10cdf180cf99a35f210c1655fbfdd74f13b1b5046591f8403873d"
+ "12239834dd6c4eceb42bf7482e1794a1601357b629ddfa971f2ed273b1"
+ "46ec1ca06d0adf55dd91d65c37297bda78c6d210c0bc26e558302",
+ 16,
+ ),
+ "p": int(
+ "ea1fb1af22881558ef93be8a5f8653c5a559434c49c8c2c12ace"
+ "5e9c41434c9cf0a8e9498acb0f4663c08b4484eace845f6fb17d"
+ "ac62c98e706af0fc74e4da1c6c2b3fbf5a1d58ff82fc1a66f3e8b122"
+ "52c40278fff9dd7f102eed2cb5b7323ebf1908c234d935414dded7f8d2"
+ "44e54561b0dca39b301de8c49da9fb23df33c6182e3f983208c560fb5"
+ "119fbf78ebe3e6564ee235c6a15cbb9ac247baba5a423bc6582a1a9d8a"
+ "2b4f0e9e3d9dbac122f750dd754325135257488b1f6ecabf21bff2947"
+ "fe0d3b2cb7ffe67f4e7fcdf1214f6053e72a5bb0dd20a0e9fe6db2df0a"
+ "908c36e95e60bf49ca4368b8b892b9c79f61ef91c47567c40e1f80ac"
+ "5aa66ef7",
+ 16,
+ ),
+ "q": int(
+ "8ec73f3761caf5fdfe6e4e82098bf10f898740dcb808204bf6b1"
+ "8f507192c19d",
+ 16,
+ ),
+ "x": int(
+ "0e0b95e31fda3f888059c46c3002ef8f2d6be112d0209aeb9e95"
+ "45da67aeea80",
+ 16,
+ ),
+ "y": int(
+ "778082b77ddba6f56597cc74c3a612abf2ddbd85cc81430c99ab"
+ "843c1f630b9db0139965f563978164f9bf3a8397256be714625"
+ "cd41cd7fa0067d94ea66d7e073f7125af692ad01371d4a17f45"
+ "50590378f2b074030c20e36911598a1018772f61be3b24de4be"
+ "5a388ccc09e15a92819c31dec50de9fde105b49eaa097b9d13d"
+ "9219eeb33b628facfd1c78a7159c8430d0647c506e7e3de74763c"
+ "b351eada72c00bef3c9641881e6254870c1e6599f8ca2f1bbb74f"
+ "39a905e3a34e4544168e6e50c9e3305fd09cab6ed4aff6fda6e0d"
+ "5bf375c81ac9054406d9193b003c89272f1bd83d48250134b65c77"
+ "c2b6332d38d34d9016f0e8975536ad6c348a1faedb0",
+ 16,
+ ),
+ },
+ {
+ "g": int(
+ "ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978d"
+ "b2104d7394b493c18332c64cec906a71c3778bd93341165dee8"
+ "e6cd4ca6f13afff531191194ada55ecf01ff94d6cf7c4768b82"
+ "dd29cd131aaf202aefd40e564375285c01f3220af4d70b96f1"
+ "395420d778228f1461f5d0b8e47357e87b1fe3286223b553e3"
+ "fc9928f16ae3067ded6721bedf1d1a01bfd22b9ae85fce77820d88cdf"
+ "50a6bde20668ad77a707d1c60fcc5d51c9de488610d0285eb8ff721f"
+ "f141f93a9fb23c1d1f7654c07c46e58836d1652828f71057b8aff0b077"
+ "8ef2ca934ea9d0f37daddade2d823a4d8e362721082e279d003b575ee"
+ "59fd050d105dfd71cd63154efe431a0869178d9811f4f231dc5dcf3b"
+ "0ec0f2b0f9896c32ec6c7ee7d60aa97109e09224907328d4e6acd1011"
+ "7e45774406c4c947da8020649c3168f690e0bd6e91ac67074d1d436b"
+ "58ae374523deaf6c93c1e6920db4a080b744804bb073cecfe83fa939"
+ "8cf150afa286dc7eb7949750cf5001ce104e9187f7e16859afa8fd0d"
+ "775ae",
+ 16,
+ ),
+ "p": int(
+ "f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d5828"
+ "c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a842"
+ "ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e8"
+ "0abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84ec"
+ "389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea2651"
+ "b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a1428"
+ "5a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab0605"
+ "48de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba9"
+ "844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1d"
+ "54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818f"
+ "06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673a"
+ "e4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f7476"
+ "cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c11"
+ "36f303f4b4d25ad5b692229957",
+ 16,
+ ),
+ "q": int(
+ "d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210"
+ "f6169041653b",
+ 16,
+ ),
+ "x": int(
+ "b2764c46113983777d3e7e97589f1303806d14ad9f2f1ef03309"
+ "7de954b17706",
+ 16,
+ ),
+ "y": int(
+ "814824e435e1e6f38daa239aad6dad21033afce6a3ebd35c1359348a0f2"
+ "418871968c2babfc2baf47742148828f8612183178f126504da73566b6"
+ "bab33ba1f124c15aa461555c2451d86c94ee21c3e3fc24c55527e"
+ "01b1f03adcdd8ec5cb08082803a7b6a829c3e99eeb332a2cf5c035b0c"
+ "e0078d3d414d31fa47e9726be2989b8d06da2e6cd363f5a7d1515e3f4"
+ "925e0b32adeae3025cc5a996f6fd27494ea408763de48f3bb39f6a06"
+ "514b019899b312ec570851637b8865cff3a52bf5d54ad5a19e6e400"
+ "a2d33251055d0a440b50d53f4791391dc754ad02b9eab74c46b4903"
+ "f9d76f824339914db108057af7cde657d41766a99991ac8787694f"
+ "4185d6f91d7627048f827b405ec67bf2fe56141c4c581d8c317333"
+ "624e073e5879a82437cb0c7b435c0ce434e15965db1315d648959"
+ "91e6bbe7dac040c42052408bbc53423fd31098248a58f8a67da3a"
+ "39895cd0cc927515d044c1e3cb6a3259c3d0da354cce89ea3552c"
+ "59609db10ee989986527436af21d9485ddf25f90f7dff6d2bae",
+ 16,
+ ),
+ },
+ {
+ "g": int(
+ "ce84b30ddf290a9f787a7c2f1ce92c1cbf4ef400e3cd7ce4978d"
+ "b2104d7394b493c18332c64cec906a71c3778bd93341165dee8"
+ "e6cd4ca6f13afff531191194ada55ecf01ff94d6cf7c4768b82"
+ "dd29cd131aaf202aefd40e564375285c01f3220af4d70b96f1"
+ "395420d778228f1461f5d0b8e47357e87b1fe3286223b553e3"
+ "fc9928f16ae3067ded6721bedf1d1a01bfd22b9ae85fce77820d88cdf"
+ "50a6bde20668ad77a707d1c60fcc5d51c9de488610d0285eb8ff721f"
+ "f141f93a9fb23c1d1f7654c07c46e58836d1652828f71057b8aff0b077"
+ "8ef2ca934ea9d0f37daddade2d823a4d8e362721082e279d003b575ee"
+ "59fd050d105dfd71cd63154efe431a0869178d9811f4f231dc5dcf3b"
+ "0ec0f2b0f9896c32ec6c7ee7d60aa97109e09224907328d4e6acd1011"
+ "7e45774406c4c947da8020649c3168f690e0bd6e91ac67074d1d436b"
+ "58ae374523deaf6c93c1e6920db4a080b744804bb073cecfe83fa939"
+ "8cf150afa286dc7eb7949750cf5001ce104e9187f7e16859afa8fd0d"
+ "775ae",
+ 16,
+ ),
+ "p": int(
+ "f335666dd1339165af8b9a5e3835adfe15c158e4c3c7bd53132e7d5828"
+ "c352f593a9a787760ce34b789879941f2f01f02319f6ae0b756f1a842"
+ "ba54c85612ed632ee2d79ef17f06b77c641b7b080aff52a03fc2462e8"
+ "0abc64d223723c236deeb7d201078ec01ca1fbc1763139e25099a84ec"
+ "389159c409792080736bd7caa816b92edf23f2c351f90074aa5ea2651"
+ "b372f8b58a0a65554db2561d706a63685000ac576b7e4562e262a1428"
+ "5a9c6370b290e4eb7757527d80b6c0fd5df831d36f3d1d35f12ab0605"
+ "48de1605fd15f7c7aafed688b146a02c945156e284f5b71282045aba9"
+ "844d48b5df2e9e7a5887121eae7d7b01db7cdf6ff917cd8eb50c6bf1d"
+ "54f90cce1a491a9c74fea88f7e7230b047d16b5a6027881d6f154818f"
+ "06e513faf40c8814630e4e254f17a47bfe9cb519b98289935bf17673a"
+ "e4c8033504a20a898d0032ee402b72d5986322f3bdfb27400561f7476"
+ "cd715eaabb7338b854e51fc2fa026a5a579b6dcea1b1c0559c13d3c11"
+ "36f303f4b4d25ad5b692229957",
+ 16,
+ ),
+ "q": int(
+ "d3eba6521240694015ef94412e08bf3cf8d635a455a398d6f210"
+ "f6169041653b",
+ 16,
+ ),
+ "x": int(
+ "52e3e040efb30e1befd909a0bdbcfd140d005b1bff094af97186"
+ "080262f1904d",
+ 16,
+ ),
+ "y": int(
+ "a5ae6e8f9b7a68ab0516dad4d7b7d002126f811d5a52e3d35c6d"
+ "387fcb43fd19bf7792362f9c98f8348aa058bb62376685f3d0c3"
+ "66c520d697fcd8416947151d4bbb6f32b53528a016479e99d2cd"
+ "48d1fc679027c15f0042f207984efe05c1796bca8eba678dfdd0"
+ "0b80418e3ea840557e73b09e003882f9a68edba3431d351d1ca0"
+ "7a8150b018fdbdf6c2f1ab475792a3ccaa6594472a45f8dc777b"
+ "60bf67de3e0f65c20d11b7d59faedf83fbce52617f500d9e5149"
+ "47c455274c6e900464767fb56599b81344cf6d12c25cb2b7d038"
+ "d7b166b6cf30534811c15d0e8ab880a2ac06786ae2ddde61329a"
+ "78d526f65245380ce877e979c5b50de66c9c30d66382c8f25465"
+ "3d25a1eb1d3a4897d7623399b473ce712a2184cf2da1861706c4"
+ "1466806aefe41b497db82aca6c31c8f4aa68c17d1d9e380b5799"
+ "8917655783ec96e5234a131f7299398d36f1f5f84297a55ff292"
+ "f1f060958c358fed346db2de45127ca728a9417b2c54203e33e5"
+ "3b9a061d924395b09afab8daf3e8dd7eedcec3ac",
+ 16,
+ ),
+ },
]
assert expected == load_fips_dsa_key_pair_vectors(vector_data)
def test_load_fips_dsa_sig_ver_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.0
# "SigVer" information
# Mod sizes selected: SHA-1 L=1024, N=160,SHA-384 L=2048, N=256
@@ -1902,166 +2124,236 @@ a6c9b4f8dbbe915b794497227ba62
R = 343ea0a9e66277380f604d5880fca686bffab69ca97bfba015a102a7e23dce0e
S = 6258488c770e0f5ad7b9da8bade5023fc0d17c6ec517bd08d53e6dc01ac5c2b3
Result = P
- """).splitlines()
+ """
+ ).splitlines()
expected = [
{
- 'p': int('dc5bf3a88b2d99e4c95cdd7a0501cc38630d425cf5c390af3429cff1'
- 'f35147b795caea923f0d3577158f8a0c89dabd1962c2c453306b5d70'
- 'cacfb01430aceb54e5a5fa6f9340d3bd2da612fceeb76b0ec1ebfae6'
- '35a56ab141b108e00dc76eefe2edd0c514c21c457457c39065dba9d0'
- 'ecb7569c247172d8438ad2827b60435b', 16),
- 'q': int('e956602b83d195dbe945b3ac702fc61f81571f1d', 16),
- 'g': int('d7eb9ca20a3c7a079606bafc4c9261ccaba303a5dc9fe9953f197dfe'
- '548c234895baa77f441ee6a2d97b909cbbd26ff7b869d24cae51b5c6'
- 'edb127a4b5d75cd8b46608bfa148249dffdb59807c5d7dde3fe3080c'
- 'a3a2d28312142becb1fa8e24003e21c7287108174b95d5bc711e1c8d'
- '9b1076784f5dc37a964a5e51390da713', 16),
- 'digest_algorithm': 'SHA-1',
- 'msg': binascii.unhexlify(
- b'0fe1bfee500bdb76026099b1d37553f6bdfe48c82094ef98cb309dd77733'
- b'0bedfaa2f94c823ef74ef4074b50d8706041ac0e371c7c22dcf70263b8d6'
- b'0e17a86c7c379cfda8f22469e0df9d49d59439fc99891873628fff25dda5'
- b'fac5ac794e948babdde968143ba05f1128f34fdad5875edc4cd71c6c24ba'
- b'2060ffbd439ce2b3'),
- 'x': int('1d93010c29ecfc432188942f46f19f44f0e1bb5d', 16),
- 'y': int('6240ea0647117c38fe705106d56db578f3e10130928452d4f3587881'
- 'b8a2bc6873a8befc3237f20914e2a91c7f07a928ee22adeed23d74ab'
- '7f82ea11f70497e578f7a9b4cbd6f10226222b0b4da2ea1e49813d6b'
- 'b9882fbf675c0846bb80cc891857b89b0ef1beb6cce3378a9aab5d66'
- 'ad4cb9277cf447dfe1e64434749432fb', 16),
- 'r': int('b5af307867fb8b54390013cc67020ddf1f2c0b81', 16),
- 's': int('620d3b22ab5031440c3e35eab6f481298f9e9f08', 16),
- 'result': 'P'},
- {
- 'p': int('dc5bf3a88b2d99e4c95cdd7a0501cc38630d425cf5c390af3429cff1'
- 'f35147b795caea923f0d3577158f8a0c89dabd1962c2c453306b5d70'
- 'cacfb01430aceb54e5a5fa6f9340d3bd2da612fceeb76b0ec1ebfae6'
- '35a56ab141b108e00dc76eefe2edd0c514c21c457457c39065dba9d0'
- 'ecb7569c247172d8438ad2827b60435b', 16),
- 'q': int('e956602b83d195dbe945b3ac702fc61f81571f1d', 16),
- 'g': int('d7eb9ca20a3c7a079606bafc4c9261ccaba303a5dc9fe9953f197dfe'
- '548c234895baa77f441ee6a2d97b909cbbd26ff7b869d24cae51b5c6'
- 'edb127a4b5d75cd8b46608bfa148249dffdb59807c5d7dde3fe3080c'
- 'a3a2d28312142becb1fa8e24003e21c7287108174b95d5bc711e1c8d'
- '9b1076784f5dc37a964a5e51390da713', 16),
- 'digest_algorithm': 'SHA-1',
- 'msg': binascii.unhexlify(
- b'97d50898025d2f9ba633866e968ca75e969d394edba6517204cb3dd537c2'
- b'ba38778a2dc9dbc685a915e5676fcd43bc3726bc59ce3d7a9fae35565082'
- b'a069c139fa37c90d922b126933db3fa6c5ef6b1edf00d174a51887bb7690'
- b'9c6a94fe994ecc7b7fc8f26113b17f30f9d01693df99a125b4f17e184331'
- b'c6b6e8ca00f54f3a'),
- 'x': int('350e13534692a7e0c4b7d58836046c436fbb2322', 16),
- 'y': int('69974de550fe6bd3099150faea1623ad3fb6d9bf23a07215093f3197'
- '25ad0877accffd291b6da18eb0cbe51676ceb0977504eb97c27c0b19'
- '1883f72fb2710a9fbd8bcf13be0bf854410b32f42b33ec89d3cc1cf8'
- '92bcd536c4195ca9ada302ad600c3408739935d77dc247529ca47f84'
- '4cc86f5016a2fe962c6e20ca7c4d4e8f', 16),
- 'r': int('b5d05faa7005764e8dae0327c5bf1972ff7681b9', 16),
- 's': int('18ea15bd9f00475b25204cbc23f8c23e01588015', 16),
- 'result': 'F'},
- {
- 'p': int('e7c1c86125db9ef417da1ced7ea0861bdad629216a3f3c745df42a4'
- '6b989e59f4d98425ee3c932fa3c2b6f637bdb6545bec526faa037e1'
- '1f5578a4363b9fca5eba60d6a9cbaa2befd04141d989c7356285132'
- 'c2eaf74f2d868521cdc0a17ae9a2546ef863027d3f8cc7949631fd0'
- 'e2971417a912c8b8c5c989730db6ea6e8baee0e667850429038093c'
- '851ccb6fb173bb081e0efe0bd7450e0946888f89f75e443ab93ef2d'
- 'a293a01622cf43c6dd79625d41ba8f9ef7e3086ab39134283d8e96c'
- '89249488120fd061e4a87d34af41069c0b4fd3934c31b589cbe85b6'
- '8b912718d5dab859fda7082511fad1d152044905005546e19b14aa9'
- '6585a55269bf2b831', 16),
- 'q': int('8e056ec9d4b7acb580087a6ed9ba3478711bb025d5b8d9c731ef9b3'
- '8bd43db2f', 16),
- 'g': int('dc2bfb9776786ad310c8b0cdcbba3062402613c67e6959a8d8d1b05'
- 'aab636528b7b1fe9cd33765f853d6dbe13d09f2681f8c7b1ed7886a'
- 'aed70c7bd76dbe858ffb8bd86235ddf759244678f428c6519af593d'
- 'c94eeadbd9852ba2b3d61664e8d58c29d2039af3c3d6d16f90988f6'
- 'a8c824569f3d48050e30896a9e17cd0232ef01ab8790008f6973b84'
- 'c763a72f4ae8b485abfb7e8efeb86808fa2b281d3e5d65d28f5992a'
- '34c077c5aa8026cb2fbc34a45f7e9bd216b10e6f12ecb172e9a6eb8'
- 'f2e91316905b6add1fd22e83bc2f089f1d5e6a6e6707c18ff55ddcb'
- '7954e8bceaf0efc4e8314910c03b0e51175f344faafee476a373ac9'
- '5743cec712b72cf2e', 16),
- 'digest_algorithm': 'SHA-384',
- 'msg': binascii.unhexlify(
- b'6cd6ccfd66bcd832189c5f0c77994210e3bf2c43416f0fe77c4e92f31c5'
- b'369538dc2c003f146c5ac79df43194ccf3c44d470d9f1083bd15b99b5bc'
- b'f88c32d8a9021f09ea2288d7b3bf345a12aef3949c1e121b9fb371a67c2'
- b'd1377364206ac839dd78483561426bda0303f285aa12e9c45d3cdfc6bea'
- b'e3549703b187deeb3296'),
- 'x': int('56c897b5938ad5b3d437d7e4826da586a6b3be15e893fa1aaa946f2'
- '0a028b6b3', 16),
- 'y': int('38ad44489e1a5778b9689f4dcf40e2acf23840fb954e987d6e8cb62'
- '9106328ac64e1f3c3eba48b21176ad4afe3b733bead382ee1597e1b'
- '83e4b43424f2daaba04e5bd79e1436693ac2bddb79a298f026e57e2'
- '00a252efd1e848a4a2e90be6e78f5242b468b9c0c6d2615047a5a40'
- 'b9ae7e57a519114db55bf3bed65e580f894b094630ca9c217f6accd'
- '091e72d2f22da620044ff372d7273f9445017fad492959e59600b74'
- '94dbe766a03e40125d4e6747c76f68a5b0cdc0e7d7cee12d08c6fb7'
- 'd0fb049e420a33405075ed4463296345ca695fb7feab7c1b5333ae5'
- '19fcd4bb6a043f4555378969114743d4face96cad31c0e0089da4e3'
- 'f61b6d7dabc088ab7', 16),
- 'r': int('3b85b17be240ed658beb3652c9d93e8e9eea160d35ee24596143058'
- '02963374e', 16),
- 's': int('726800a5174a53b56dce86064109c0273cd11fcfa3c92c5cd6aa910'
- '260c0e3c7', 16),
- 'result': 'F'},
- {
- 'p': int('e7c1c86125db9ef417da1ced7ea0861bdad629216a3f3c745df42a4'
- '6b989e59f4d98425ee3c932fa3c2b6f637bdb6545bec526faa037e1'
- '1f5578a4363b9fca5eba60d6a9cbaa2befd04141d989c7356285132'
- 'c2eaf74f2d868521cdc0a17ae9a2546ef863027d3f8cc7949631fd0'
- 'e2971417a912c8b8c5c989730db6ea6e8baee0e667850429038093c'
- '851ccb6fb173bb081e0efe0bd7450e0946888f89f75e443ab93ef2d'
- 'a293a01622cf43c6dd79625d41ba8f9ef7e3086ab39134283d8e96c'
- '89249488120fd061e4a87d34af41069c0b4fd3934c31b589cbe85b6'
- '8b912718d5dab859fda7082511fad1d152044905005546e19b14aa9'
- '6585a55269bf2b831', 16),
- 'q': int('8e056ec9d4b7acb580087a6ed9ba3478711bb025d5b8d9c731ef9b3'
- '8bd43db2f', 16),
- 'g': int('dc2bfb9776786ad310c8b0cdcbba3062402613c67e6959a8d8d1b05'
- 'aab636528b7b1fe9cd33765f853d6dbe13d09f2681f8c7b1ed7886a'
- 'aed70c7bd76dbe858ffb8bd86235ddf759244678f428c6519af593d'
- 'c94eeadbd9852ba2b3d61664e8d58c29d2039af3c3d6d16f90988f6'
- 'a8c824569f3d48050e30896a9e17cd0232ef01ab8790008f6973b84'
- 'c763a72f4ae8b485abfb7e8efeb86808fa2b281d3e5d65d28f5992a'
- '34c077c5aa8026cb2fbc34a45f7e9bd216b10e6f12ecb172e9a6eb8'
- 'f2e91316905b6add1fd22e83bc2f089f1d5e6a6e6707c18ff55ddcb'
- '7954e8bceaf0efc4e8314910c03b0e51175f344faafee476a373ac9'
- '5743cec712b72cf2e', 16),
- 'digest_algorithm': 'SHA-384',
- 'msg': binascii.unhexlify(
- b'3ad6b0884f358dea09c31a9abc40c45a6000611fc2b907b30eac00413fd'
- b'2819de7015488a411609d46c499b8f7afa1b78b352ac7f8535bd805b8ff'
- b'2a5eae557098c668f7ccd73af886d6823a6d456c29931ee864ed46d7673'
- b'82785728c2a83fcff5271007d2a67d06fa205fd7b9d1a42ea5d6dc76e5e'
- b'18a9eb148cd1e8b262ae'),
- 'x': int('2faf566a9f057960f1b50c69508f483d9966d6e35743591f3a677a9'
- 'dc40e1555', 16),
- 'y': int('926425d617babe87c442b03903e32ba5bbf0cd9d602b59c4df791a4d'
- '64a6d4333ca0c0d370552539197d327dcd1bbf8c454f24b03fc7805f'
- '862db34c7b066ddfddbb11dbd010b27123062d028fe041cb56a2e774'
- '88348ae0ab6705d87aac4d4e9e6600e9e706326d9979982cffa839be'
- 'b9eacc3963bcca455a507e80c1c37ad4e765b2c9c0477a075e9bc584'
- 'feacdf3a35a9391d4711f14e197c54022282bfed9a191213d64127f1'
- '7a9c5affec26e0c71f15d3a5b16098fec118c45bf8bb2f3b1560df09'
- '49254c1c0aeb0a16d5a95a40fab8521fbe8ea77c51169b587cc3360e'
- '5733e6a23b9fded8c40724ea1f9e93614b3a6c9b4f8dbbe915b79449'
- '7227ba62', 16),
- 'r': int('343ea0a9e66277380f604d5880fca686bffab69ca97bfba015a102a'
- '7e23dce0e', 16),
- 's': int('6258488c770e0f5ad7b9da8bade5023fc0d17c6ec517bd08d53e6dc'
- '01ac5c2b3', 16),
- 'result': 'P'}
+ "p": int(
+ "dc5bf3a88b2d99e4c95cdd7a0501cc38630d425cf5c390af3429cff1"
+ "f35147b795caea923f0d3577158f8a0c89dabd1962c2c453306b5d70"
+ "cacfb01430aceb54e5a5fa6f9340d3bd2da612fceeb76b0ec1ebfae6"
+ "35a56ab141b108e00dc76eefe2edd0c514c21c457457c39065dba9d0"
+ "ecb7569c247172d8438ad2827b60435b",
+ 16,
+ ),
+ "q": int("e956602b83d195dbe945b3ac702fc61f81571f1d", 16),
+ "g": int(
+ "d7eb9ca20a3c7a079606bafc4c9261ccaba303a5dc9fe9953f197dfe"
+ "548c234895baa77f441ee6a2d97b909cbbd26ff7b869d24cae51b5c6"
+ "edb127a4b5d75cd8b46608bfa148249dffdb59807c5d7dde3fe3080c"
+ "a3a2d28312142becb1fa8e24003e21c7287108174b95d5bc711e1c8d"
+ "9b1076784f5dc37a964a5e51390da713",
+ 16,
+ ),
+ "digest_algorithm": "SHA-1",
+ "msg": binascii.unhexlify(
+ b"0fe1bfee500bdb76026099b1d37553f6bdfe48c82094ef98cb309dd77733"
+ b"0bedfaa2f94c823ef74ef4074b50d8706041ac0e371c7c22dcf70263b8d6"
+ b"0e17a86c7c379cfda8f22469e0df9d49d59439fc99891873628fff25dda5"
+ b"fac5ac794e948babdde968143ba05f1128f34fdad5875edc4cd71c6c24ba"
+ b"2060ffbd439ce2b3"
+ ),
+ "x": int("1d93010c29ecfc432188942f46f19f44f0e1bb5d", 16),
+ "y": int(
+ "6240ea0647117c38fe705106d56db578f3e10130928452d4f3587881"
+ "b8a2bc6873a8befc3237f20914e2a91c7f07a928ee22adeed23d74ab"
+ "7f82ea11f70497e578f7a9b4cbd6f10226222b0b4da2ea1e49813d6b"
+ "b9882fbf675c0846bb80cc891857b89b0ef1beb6cce3378a9aab5d66"
+ "ad4cb9277cf447dfe1e64434749432fb",
+ 16,
+ ),
+ "r": int("b5af307867fb8b54390013cc67020ddf1f2c0b81", 16),
+ "s": int("620d3b22ab5031440c3e35eab6f481298f9e9f08", 16),
+ "result": "P",
+ },
+ {
+ "p": int(
+ "dc5bf3a88b2d99e4c95cdd7a0501cc38630d425cf5c390af3429cff1"
+ "f35147b795caea923f0d3577158f8a0c89dabd1962c2c453306b5d70"
+ "cacfb01430aceb54e5a5fa6f9340d3bd2da612fceeb76b0ec1ebfae6"
+ "35a56ab141b108e00dc76eefe2edd0c514c21c457457c39065dba9d0"
+ "ecb7569c247172d8438ad2827b60435b",
+ 16,
+ ),
+ "q": int("e956602b83d195dbe945b3ac702fc61f81571f1d", 16),
+ "g": int(
+ "d7eb9ca20a3c7a079606bafc4c9261ccaba303a5dc9fe9953f197dfe"
+ "548c234895baa77f441ee6a2d97b909cbbd26ff7b869d24cae51b5c6"
+ "edb127a4b5d75cd8b46608bfa148249dffdb59807c5d7dde3fe3080c"
+ "a3a2d28312142becb1fa8e24003e21c7287108174b95d5bc711e1c8d"
+ "9b1076784f5dc37a964a5e51390da713",
+ 16,
+ ),
+ "digest_algorithm": "SHA-1",
+ "msg": binascii.unhexlify(
+ b"97d50898025d2f9ba633866e968ca75e969d394edba6517204cb3dd537c2"
+ b"ba38778a2dc9dbc685a915e5676fcd43bc3726bc59ce3d7a9fae35565082"
+ b"a069c139fa37c90d922b126933db3fa6c5ef6b1edf00d174a51887bb7690"
+ b"9c6a94fe994ecc7b7fc8f26113b17f30f9d01693df99a125b4f17e184331"
+ b"c6b6e8ca00f54f3a"
+ ),
+ "x": int("350e13534692a7e0c4b7d58836046c436fbb2322", 16),
+ "y": int(
+ "69974de550fe6bd3099150faea1623ad3fb6d9bf23a07215093f3197"
+ "25ad0877accffd291b6da18eb0cbe51676ceb0977504eb97c27c0b19"
+ "1883f72fb2710a9fbd8bcf13be0bf854410b32f42b33ec89d3cc1cf8"
+ "92bcd536c4195ca9ada302ad600c3408739935d77dc247529ca47f84"
+ "4cc86f5016a2fe962c6e20ca7c4d4e8f",
+ 16,
+ ),
+ "r": int("b5d05faa7005764e8dae0327c5bf1972ff7681b9", 16),
+ "s": int("18ea15bd9f00475b25204cbc23f8c23e01588015", 16),
+ "result": "F",
+ },
+ {
+ "p": int(
+ "e7c1c86125db9ef417da1ced7ea0861bdad629216a3f3c745df42a4"
+ "6b989e59f4d98425ee3c932fa3c2b6f637bdb6545bec526faa037e1"
+ "1f5578a4363b9fca5eba60d6a9cbaa2befd04141d989c7356285132"
+ "c2eaf74f2d868521cdc0a17ae9a2546ef863027d3f8cc7949631fd0"
+ "e2971417a912c8b8c5c989730db6ea6e8baee0e667850429038093c"
+ "851ccb6fb173bb081e0efe0bd7450e0946888f89f75e443ab93ef2d"
+ "a293a01622cf43c6dd79625d41ba8f9ef7e3086ab39134283d8e96c"
+ "89249488120fd061e4a87d34af41069c0b4fd3934c31b589cbe85b6"
+ "8b912718d5dab859fda7082511fad1d152044905005546e19b14aa9"
+ "6585a55269bf2b831",
+ 16,
+ ),
+ "q": int(
+ "8e056ec9d4b7acb580087a6ed9ba3478711bb025d5b8d9c731ef9b3"
+ "8bd43db2f",
+ 16,
+ ),
+ "g": int(
+ "dc2bfb9776786ad310c8b0cdcbba3062402613c67e6959a8d8d1b05"
+ "aab636528b7b1fe9cd33765f853d6dbe13d09f2681f8c7b1ed7886a"
+ "aed70c7bd76dbe858ffb8bd86235ddf759244678f428c6519af593d"
+ "c94eeadbd9852ba2b3d61664e8d58c29d2039af3c3d6d16f90988f6"
+ "a8c824569f3d48050e30896a9e17cd0232ef01ab8790008f6973b84"
+ "c763a72f4ae8b485abfb7e8efeb86808fa2b281d3e5d65d28f5992a"
+ "34c077c5aa8026cb2fbc34a45f7e9bd216b10e6f12ecb172e9a6eb8"
+ "f2e91316905b6add1fd22e83bc2f089f1d5e6a6e6707c18ff55ddcb"
+ "7954e8bceaf0efc4e8314910c03b0e51175f344faafee476a373ac9"
+ "5743cec712b72cf2e",
+ 16,
+ ),
+ "digest_algorithm": "SHA-384",
+ "msg": binascii.unhexlify(
+ b"6cd6ccfd66bcd832189c5f0c77994210e3bf2c43416f0fe77c4e92f31c5"
+ b"369538dc2c003f146c5ac79df43194ccf3c44d470d9f1083bd15b99b5bc"
+ b"f88c32d8a9021f09ea2288d7b3bf345a12aef3949c1e121b9fb371a67c2"
+ b"d1377364206ac839dd78483561426bda0303f285aa12e9c45d3cdfc6bea"
+ b"e3549703b187deeb3296"
+ ),
+ "x": int(
+ "56c897b5938ad5b3d437d7e4826da586a6b3be15e893fa1aaa946f2"
+ "0a028b6b3",
+ 16,
+ ),
+ "y": int(
+ "38ad44489e1a5778b9689f4dcf40e2acf23840fb954e987d6e8cb62"
+ "9106328ac64e1f3c3eba48b21176ad4afe3b733bead382ee1597e1b"
+ "83e4b43424f2daaba04e5bd79e1436693ac2bddb79a298f026e57e2"
+ "00a252efd1e848a4a2e90be6e78f5242b468b9c0c6d2615047a5a40"
+ "b9ae7e57a519114db55bf3bed65e580f894b094630ca9c217f6accd"
+ "091e72d2f22da620044ff372d7273f9445017fad492959e59600b74"
+ "94dbe766a03e40125d4e6747c76f68a5b0cdc0e7d7cee12d08c6fb7"
+ "d0fb049e420a33405075ed4463296345ca695fb7feab7c1b5333ae5"
+ "19fcd4bb6a043f4555378969114743d4face96cad31c0e0089da4e3"
+ "f61b6d7dabc088ab7",
+ 16,
+ ),
+ "r": int(
+ "3b85b17be240ed658beb3652c9d93e8e9eea160d35ee24596143058"
+ "02963374e",
+ 16,
+ ),
+ "s": int(
+ "726800a5174a53b56dce86064109c0273cd11fcfa3c92c5cd6aa910"
+ "260c0e3c7",
+ 16,
+ ),
+ "result": "F",
+ },
+ {
+ "p": int(
+ "e7c1c86125db9ef417da1ced7ea0861bdad629216a3f3c745df42a4"
+ "6b989e59f4d98425ee3c932fa3c2b6f637bdb6545bec526faa037e1"
+ "1f5578a4363b9fca5eba60d6a9cbaa2befd04141d989c7356285132"
+ "c2eaf74f2d868521cdc0a17ae9a2546ef863027d3f8cc7949631fd0"
+ "e2971417a912c8b8c5c989730db6ea6e8baee0e667850429038093c"
+ "851ccb6fb173bb081e0efe0bd7450e0946888f89f75e443ab93ef2d"
+ "a293a01622cf43c6dd79625d41ba8f9ef7e3086ab39134283d8e96c"
+ "89249488120fd061e4a87d34af41069c0b4fd3934c31b589cbe85b6"
+ "8b912718d5dab859fda7082511fad1d152044905005546e19b14aa9"
+ "6585a55269bf2b831",
+ 16,
+ ),
+ "q": int(
+ "8e056ec9d4b7acb580087a6ed9ba3478711bb025d5b8d9c731ef9b3"
+ "8bd43db2f",
+ 16,
+ ),
+ "g": int(
+ "dc2bfb9776786ad310c8b0cdcbba3062402613c67e6959a8d8d1b05"
+ "aab636528b7b1fe9cd33765f853d6dbe13d09f2681f8c7b1ed7886a"
+ "aed70c7bd76dbe858ffb8bd86235ddf759244678f428c6519af593d"
+ "c94eeadbd9852ba2b3d61664e8d58c29d2039af3c3d6d16f90988f6"
+ "a8c824569f3d48050e30896a9e17cd0232ef01ab8790008f6973b84"
+ "c763a72f4ae8b485abfb7e8efeb86808fa2b281d3e5d65d28f5992a"
+ "34c077c5aa8026cb2fbc34a45f7e9bd216b10e6f12ecb172e9a6eb8"
+ "f2e91316905b6add1fd22e83bc2f089f1d5e6a6e6707c18ff55ddcb"
+ "7954e8bceaf0efc4e8314910c03b0e51175f344faafee476a373ac9"
+ "5743cec712b72cf2e",
+ 16,
+ ),
+ "digest_algorithm": "SHA-384",
+ "msg": binascii.unhexlify(
+ b"3ad6b0884f358dea09c31a9abc40c45a6000611fc2b907b30eac00413fd"
+ b"2819de7015488a411609d46c499b8f7afa1b78b352ac7f8535bd805b8ff"
+ b"2a5eae557098c668f7ccd73af886d6823a6d456c29931ee864ed46d7673"
+ b"82785728c2a83fcff5271007d2a67d06fa205fd7b9d1a42ea5d6dc76e5e"
+ b"18a9eb148cd1e8b262ae"
+ ),
+ "x": int(
+ "2faf566a9f057960f1b50c69508f483d9966d6e35743591f3a677a9"
+ "dc40e1555",
+ 16,
+ ),
+ "y": int(
+ "926425d617babe87c442b03903e32ba5bbf0cd9d602b59c4df791a4d"
+ "64a6d4333ca0c0d370552539197d327dcd1bbf8c454f24b03fc7805f"
+ "862db34c7b066ddfddbb11dbd010b27123062d028fe041cb56a2e774"
+ "88348ae0ab6705d87aac4d4e9e6600e9e706326d9979982cffa839be"
+ "b9eacc3963bcca455a507e80c1c37ad4e765b2c9c0477a075e9bc584"
+ "feacdf3a35a9391d4711f14e197c54022282bfed9a191213d64127f1"
+ "7a9c5affec26e0c71f15d3a5b16098fec118c45bf8bb2f3b1560df09"
+ "49254c1c0aeb0a16d5a95a40fab8521fbe8ea77c51169b587cc3360e"
+ "5733e6a23b9fded8c40724ea1f9e93614b3a6c9b4f8dbbe915b79449"
+ "7227ba62",
+ 16,
+ ),
+ "r": int(
+ "343ea0a9e66277380f604d5880fca686bffab69ca97bfba015a102a"
+ "7e23dce0e",
+ 16,
+ ),
+ "s": int(
+ "6258488c770e0f5ad7b9da8bade5023fc0d17c6ec517bd08d53e6dc"
+ "01ac5c2b3",
+ 16,
+ ),
+ "result": "P",
+ },
]
assert expected == load_fips_dsa_sig_vectors(vector_data)
def test_load_fips_dsa_sig_gen_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.2
# "SigGen" information for "dsa2_values"
# Mod sizes selected: SHA-1 L=1024, N=160, SHA-256 L=2048, N=256
@@ -2145,155 +2437,219 @@ e284935a53f67a1aa8e25d8ad5c4ad55d83aef883a4d9eeb6297e6a53f65049ba9e2c6b7953a7\
60bc1dc46f78ceaaa2c02f5375dd82e708744aa40b15799eb81d7e5b1a
R = bcd490568c0a89ba311bef88ea4f4b03d273e793722722327095a378dd6f3522
S = 74498fc43091fcdd2d1ef0775f8286945a01cd72b805256b0451f9cbd943cf82
- """).splitlines()
+ """
+ ).splitlines()
expected = [
{
- 'p': int('a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed325'
- '6b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4'
- 'c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b0'
- '2e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd'
- '5ebe2d1229681b5b06439ac9c7e9d8bde283', 16),
- 'q': int('f85f0f83ac4df7ea0cdf8f469bfeeaea14156495', 16),
- 'g': int('2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df1'
- '31f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40'
- 'b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd'
- '64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909'
- 'a6a3a99bbe089216368171bd0ba81de4fe33', 16),
- 'digest_algorithm': 'SHA-1',
- 'msg': binascii.unhexlify(
- b'3b46736d559bd4e0c2c1b2553a33ad3c6cf23cac998d3d0c0e8fa4b19bc'
- b'a06f2f386db2dcff9dca4f40ad8f561ffc308b46c5f31a7735b5fa7e0f9'
- b'e6cb512e63d7eea05538d66a75cd0d4234b5ccf6c1715ccaaf9cdc0a222'
- b'8135f716ee9bdee7fc13ec27a03a6d11c5c5b3685f51900b1337153bc6c'
- b'4e8f52920c33fa37f4e7'),
- 'y': int('313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761b'
- 'bb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a'
- '6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae1'
- '9c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32'
- '786d96f5a31aedf75364008ad4fffebb970b', 16),
- 'r': int('50ed0e810e3f1c7cb6ac62332058448bd8b284c0', 16),
- 's': int('c6aded17216b46b7e4b6f2a97c1ad7cc3da83fde', 16)},
- {
- 'p': int('a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed325'
- '6b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4'
- 'c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b0'
- '2e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd'
- '5ebe2d1229681b5b06439ac9c7e9d8bde283', 16),
- 'q': int('f85f0f83ac4df7ea0cdf8f469bfeeaea14156495', 16),
- 'g': int('2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df1'
- '31f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40'
- 'b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd'
- '64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909'
- 'a6a3a99bbe089216368171bd0ba81de4fe33', 16),
- 'digest_algorithm': 'SHA-1',
- 'msg': binascii.unhexlify(
- b'd2bcb53b044b3e2e4b61ba2f91c0995fb83a6a97525e66441a3b489d959'
- b'4238bc740bdeea0f718a769c977e2de003877b5d7dc25b182ae533db33e'
- b'78f2c3ff0645f2137abc137d4e7d93ccf24f60b18a820bc07c7b4b5fe08'
- b'b4f9e7d21b256c18f3b9d49acc4f93e2ce6f3754c7807757d2e11760426'
- b'12cb32fc3f4f70700e25'),
- 'y': int('29bdd759aaa62d4bf16b4861c81cf42eac2e1637b9ecba512bdbc13'
- 'ac12a80ae8de2526b899ae5e4a231aef884197c944c732693a634d7'
- '659abc6975a773f8d3cd5a361fe2492386a3c09aaef12e4a7e73ad7'
- 'dfc3637f7b093f2c40d6223a195c136adf2ea3fbf8704a675aa7817'
- 'aa7ec7f9adfb2854d4e05c3ce7f76560313b', 16),
- 'r': int('a26c00b5750a2d27fe7435b93476b35438b4d8ab', 16),
- 's': int('61c9bfcb2938755afa7dad1d1e07c6288617bf70', 16)},
- {
- 'p': int('a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe1'
- '3a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bb'
- 'd67906c081e585410e38480ead51684dac3a38f7b64c9eb109f1973'
- '9a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee4'
- '1047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543e'
- 'adb7718f317bf5d9577a6156561b082a10029cd44012b18de684450'
- '9fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d1'
- '25dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31'
- 'b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff00'
- '7e8be2f0be06cc15f', 16),
- 'q': int('e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e686'
- '04d6b9dfb', 16),
- 'g': int('5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa'
- '104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff'
- '8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee49'
- '3643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a533'
- '0392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec'
- '1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f3'
- '5ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8'
- '347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d'
- '2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb'
- '64fd9a6c5b75c4561', 16),
- 'digest_algorithm': 'SHA-256',
- 'msg': binascii.unhexlify(
- b'4e3a28bcf90d1d2e75f075d9fbe55b36c5529b17bc3a9ccaba6935c9e20'
- b'548255b3dfae0f91db030c12f2c344b3a29c4151c5b209f5e319fdf1c23'
- b'b190f64f1fe5b330cb7c8fa952f9d90f13aff1cb11d63181da9efc6f7e1'
- b'5bfed4862d1a62c7dcf3ba8bf1ff304b102b1ec3f1497dddf09712cf323'
- b'f5610a9d10c3d9132659'),
- 'y': int('5a55dceddd1134ee5f11ed85deb4d634a3643f5f36dc3a706892564'
- '69a0b651ad22880f14ab85719434f9c0e407e60ea420e2a0cd29422'
- 'c4899c416359dbb1e592456f2b3cce233259c117542fd05f31ea25b'
- '015d9121c890b90e0bad033be1368d229985aac7226d1c8c2eab325'
- 'ef3b2cd59d3b9f7de7dbc94af1a9339eb430ca36c26c46ecfa6c548'
- '1711496f624e188ad7540ef5df26f8efacb820bd17a1f618acb50c9'
- 'bc197d4cb7ccac45d824a3bf795c234b556b06aeb92917345325208'
- '4003f69fe98045fe74002ba658f93475622f76791d9b2623d1b5fff'
- '2cc16844746efd2d30a6a8134bfc4c8cc80a46107901fb973c28fc5'
- '53130f3286c1489da', 16),
- 'r': int('633055e055f237c38999d81c397848c38cce80a55b649d9e7905c29'
- '8e2a51447', 16),
- 's': int('2bbf68317660ec1e4b154915027b0bc00ee19cfc0bf75d01930504f'
- '2ce10a8b0', 16)},
- {
- 'p': int('a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe1'
- '3a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bb'
- 'd67906c081e585410e38480ead51684dac3a38f7b64c9eb109f1973'
- '9a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee4'
- '1047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543e'
- 'adb7718f317bf5d9577a6156561b082a10029cd44012b18de684450'
- '9fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d1'
- '25dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31'
- 'b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff00'
- '7e8be2f0be06cc15f', 16),
- 'q': int('e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e686'
- '04d6b9dfb', 16),
- 'g': int('5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa'
- '104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff'
- '8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee49'
- '3643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a533'
- '0392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec'
- '1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f3'
- '5ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8'
- '347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d'
- '2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb'
- '64fd9a6c5b75c4561', 16),
- 'digest_algorithm': 'SHA-256',
- 'msg': binascii.unhexlify(
- b'a733b3f588d5ac9b9d4fe2f804df8c256403a9f8eef6f191fc48e1267fb'
- b'5b4d546ba11e77b667844e489bf0d5f72990aeb061d01ccd7949a23def7'
- b'4a803b7d92d51abfadeb4885ffd8ffd58ab87548a15c087a39b8993b2fa'
- b'64c9d31a594eeb7512da16955834336a234435c5a9d0dd9b15a94e11615'
- b'4dea63fdc8dd7a512181'),
- 'y': int('356ed47537fbf02cb30a8cee0537f300dff1d0c467399ce70b87a87'
- '58d5ec9dd256246fccaeb9dfe109f2a984f2ddaa87aad54ce0d31f9'
- '07e504521baf4207d7073b0a4a9fc67d8ddda99f87aed6e0367cec2'
- '7f9c608af743bf1ee6e11d55a182d43b024ace534029b866f642282'
- '8bb81a39aae9601ee81c7f81dd358e69f4e2edfa4654d8a65bc6431'
- '1dc86aac4abc1fc7a3f65159661a0d8e288eb8d665cb0adf5ac3d6b'
- 'a8e9453facf7542393ae24fd50451d3828086558f7ec528e284935a'
- '53f67a1aa8e25d8ad5c4ad55d83aef883a4d9eeb6297e6a53f65049'
- 'ba9e2c6b7953a760bc1dc46f78ceaaa2c02f5375dd82e708744aa40'
- 'b15799eb81d7e5b1a', 16),
- 'r': int('bcd490568c0a89ba311bef88ea4f4b03d273e793722722327095a37'
- '8dd6f3522', 16),
- 's': int('74498fc43091fcdd2d1ef0775f8286945a01cd72b805256b0451f9c'
- 'bd943cf82', 16)}
+ "p": int(
+ "a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed325"
+ "6b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4"
+ "c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b0"
+ "2e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd"
+ "5ebe2d1229681b5b06439ac9c7e9d8bde283",
+ 16,
+ ),
+ "q": int("f85f0f83ac4df7ea0cdf8f469bfeeaea14156495", 16),
+ "g": int(
+ "2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df1"
+ "31f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40"
+ "b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd"
+ "64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909"
+ "a6a3a99bbe089216368171bd0ba81de4fe33",
+ 16,
+ ),
+ "digest_algorithm": "SHA-1",
+ "msg": binascii.unhexlify(
+ b"3b46736d559bd4e0c2c1b2553a33ad3c6cf23cac998d3d0c0e8fa4b19bc"
+ b"a06f2f386db2dcff9dca4f40ad8f561ffc308b46c5f31a7735b5fa7e0f9"
+ b"e6cb512e63d7eea05538d66a75cd0d4234b5ccf6c1715ccaaf9cdc0a222"
+ b"8135f716ee9bdee7fc13ec27a03a6d11c5c5b3685f51900b1337153bc6c"
+ b"4e8f52920c33fa37f4e7"
+ ),
+ "y": int(
+ "313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761b"
+ "bb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a"
+ "6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae1"
+ "9c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32"
+ "786d96f5a31aedf75364008ad4fffebb970b",
+ 16,
+ ),
+ "r": int("50ed0e810e3f1c7cb6ac62332058448bd8b284c0", 16),
+ "s": int("c6aded17216b46b7e4b6f2a97c1ad7cc3da83fde", 16),
+ },
+ {
+ "p": int(
+ "a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed325"
+ "6b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4"
+ "c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b0"
+ "2e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd"
+ "5ebe2d1229681b5b06439ac9c7e9d8bde283",
+ 16,
+ ),
+ "q": int("f85f0f83ac4df7ea0cdf8f469bfeeaea14156495", 16),
+ "g": int(
+ "2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df1"
+ "31f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40"
+ "b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd"
+ "64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909"
+ "a6a3a99bbe089216368171bd0ba81de4fe33",
+ 16,
+ ),
+ "digest_algorithm": "SHA-1",
+ "msg": binascii.unhexlify(
+ b"d2bcb53b044b3e2e4b61ba2f91c0995fb83a6a97525e66441a3b489d959"
+ b"4238bc740bdeea0f718a769c977e2de003877b5d7dc25b182ae533db33e"
+ b"78f2c3ff0645f2137abc137d4e7d93ccf24f60b18a820bc07c7b4b5fe08"
+ b"b4f9e7d21b256c18f3b9d49acc4f93e2ce6f3754c7807757d2e11760426"
+ b"12cb32fc3f4f70700e25"
+ ),
+ "y": int(
+ "29bdd759aaa62d4bf16b4861c81cf42eac2e1637b9ecba512bdbc13"
+ "ac12a80ae8de2526b899ae5e4a231aef884197c944c732693a634d7"
+ "659abc6975a773f8d3cd5a361fe2492386a3c09aaef12e4a7e73ad7"
+ "dfc3637f7b093f2c40d6223a195c136adf2ea3fbf8704a675aa7817"
+ "aa7ec7f9adfb2854d4e05c3ce7f76560313b",
+ 16,
+ ),
+ "r": int("a26c00b5750a2d27fe7435b93476b35438b4d8ab", 16),
+ "s": int("61c9bfcb2938755afa7dad1d1e07c6288617bf70", 16),
+ },
+ {
+ "p": int(
+ "a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe1"
+ "3a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bb"
+ "d67906c081e585410e38480ead51684dac3a38f7b64c9eb109f1973"
+ "9a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee4"
+ "1047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543e"
+ "adb7718f317bf5d9577a6156561b082a10029cd44012b18de684450"
+ "9fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d1"
+ "25dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31"
+ "b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff00"
+ "7e8be2f0be06cc15f",
+ 16,
+ ),
+ "q": int(
+ "e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e686"
+ "04d6b9dfb",
+ 16,
+ ),
+ "g": int(
+ "5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa"
+ "104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff"
+ "8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee49"
+ "3643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a533"
+ "0392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec"
+ "1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f3"
+ "5ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8"
+ "347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d"
+ "2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb"
+ "64fd9a6c5b75c4561",
+ 16,
+ ),
+ "digest_algorithm": "SHA-256",
+ "msg": binascii.unhexlify(
+ b"4e3a28bcf90d1d2e75f075d9fbe55b36c5529b17bc3a9ccaba6935c9e20"
+ b"548255b3dfae0f91db030c12f2c344b3a29c4151c5b209f5e319fdf1c23"
+ b"b190f64f1fe5b330cb7c8fa952f9d90f13aff1cb11d63181da9efc6f7e1"
+ b"5bfed4862d1a62c7dcf3ba8bf1ff304b102b1ec3f1497dddf09712cf323"
+ b"f5610a9d10c3d9132659"
+ ),
+ "y": int(
+ "5a55dceddd1134ee5f11ed85deb4d634a3643f5f36dc3a706892564"
+ "69a0b651ad22880f14ab85719434f9c0e407e60ea420e2a0cd29422"
+ "c4899c416359dbb1e592456f2b3cce233259c117542fd05f31ea25b"
+ "015d9121c890b90e0bad033be1368d229985aac7226d1c8c2eab325"
+ "ef3b2cd59d3b9f7de7dbc94af1a9339eb430ca36c26c46ecfa6c548"
+ "1711496f624e188ad7540ef5df26f8efacb820bd17a1f618acb50c9"
+ "bc197d4cb7ccac45d824a3bf795c234b556b06aeb92917345325208"
+ "4003f69fe98045fe74002ba658f93475622f76791d9b2623d1b5fff"
+ "2cc16844746efd2d30a6a8134bfc4c8cc80a46107901fb973c28fc5"
+ "53130f3286c1489da",
+ 16,
+ ),
+ "r": int(
+ "633055e055f237c38999d81c397848c38cce80a55b649d9e7905c29"
+ "8e2a51447",
+ 16,
+ ),
+ "s": int(
+ "2bbf68317660ec1e4b154915027b0bc00ee19cfc0bf75d01930504f"
+ "2ce10a8b0",
+ 16,
+ ),
+ },
+ {
+ "p": int(
+ "a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe1"
+ "3a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bb"
+ "d67906c081e585410e38480ead51684dac3a38f7b64c9eb109f1973"
+ "9a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee4"
+ "1047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543e"
+ "adb7718f317bf5d9577a6156561b082a10029cd44012b18de684450"
+ "9fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d1"
+ "25dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31"
+ "b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff00"
+ "7e8be2f0be06cc15f",
+ 16,
+ ),
+ "q": int(
+ "e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e686"
+ "04d6b9dfb",
+ 16,
+ ),
+ "g": int(
+ "5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa"
+ "104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff"
+ "8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee49"
+ "3643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a533"
+ "0392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec"
+ "1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f3"
+ "5ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8"
+ "347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d"
+ "2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb"
+ "64fd9a6c5b75c4561",
+ 16,
+ ),
+ "digest_algorithm": "SHA-256",
+ "msg": binascii.unhexlify(
+ b"a733b3f588d5ac9b9d4fe2f804df8c256403a9f8eef6f191fc48e1267fb"
+ b"5b4d546ba11e77b667844e489bf0d5f72990aeb061d01ccd7949a23def7"
+ b"4a803b7d92d51abfadeb4885ffd8ffd58ab87548a15c087a39b8993b2fa"
+ b"64c9d31a594eeb7512da16955834336a234435c5a9d0dd9b15a94e11615"
+ b"4dea63fdc8dd7a512181"
+ ),
+ "y": int(
+ "356ed47537fbf02cb30a8cee0537f300dff1d0c467399ce70b87a87"
+ "58d5ec9dd256246fccaeb9dfe109f2a984f2ddaa87aad54ce0d31f9"
+ "07e504521baf4207d7073b0a4a9fc67d8ddda99f87aed6e0367cec2"
+ "7f9c608af743bf1ee6e11d55a182d43b024ace534029b866f642282"
+ "8bb81a39aae9601ee81c7f81dd358e69f4e2edfa4654d8a65bc6431"
+ "1dc86aac4abc1fc7a3f65159661a0d8e288eb8d665cb0adf5ac3d6b"
+ "a8e9453facf7542393ae24fd50451d3828086558f7ec528e284935a"
+ "53f67a1aa8e25d8ad5c4ad55d83aef883a4d9eeb6297e6a53f65049"
+ "ba9e2c6b7953a760bc1dc46f78ceaaa2c02f5375dd82e708744aa40"
+ "b15799eb81d7e5b1a",
+ 16,
+ ),
+ "r": int(
+ "bcd490568c0a89ba311bef88ea4f4b03d273e793722722327095a37"
+ "8dd6f3522",
+ 16,
+ ),
+ "s": int(
+ "74498fc43091fcdd2d1ef0775f8286945a01cd72b805256b0451f9c"
+ "bd943cf82",
+ 16,
+ ),
+ },
]
assert expected == load_fips_dsa_sig_vectors(vector_data)
def test_load_fips_ecdsa_key_pair_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.0
# "Key Pair" information
# Curves selected: P-192 K-233 B-571
@@ -2346,67 +2702,97 @@ f8357e3710bcda1833b30e297d4bf637938b995d231e557d13f062e81e830af5ab052208ead
7d6289980819292a719eb247195529ea60ad62862de0a26c72bfc49ecc81c2f9ed704e3168f
Qy = 0721496cf16f988b1aabef3368450441df8439a0ca794170f270ead56203d675b57f5\
a4090a3a2f602a77ff3bac1417f7e25a683f667b3b91f105016a47afad46a0367b18e2bdf0c
- """).splitlines()
+ """
+ ).splitlines()
expected = [
{
"curve": "secp192r1",
"d": int("e5ce89a34adddf25ff3bf1ffe6803f57d0220de3118798ea", 16),
"x": int("8abf7b3ceb2b02438af19543d3e5b1d573fa9ac60085840f", 16),
- "y": int("a87f80182dcd56a6a061f81f7da393e7cffd5e0738c6b245", 16)
+ "y": int("a87f80182dcd56a6a061f81f7da393e7cffd5e0738c6b245", 16),
},
-
{
"curve": "secp192r1",
"d": int("7d14435714ad13ff23341cb567cc91198ff8617cc39751b2", 16),
"x": int("39dc723b19527daa1e80425209c56463481b9b47c51f8cbd", 16),
"y": int("432a3e84f2a16418834fabaf6b7d2341669512951f1672ad", 16),
},
-
{
"curve": "sect233k1",
- "d": int("1da7422b50e3ff051f2aaaed10acea6cbf6110c517da2f4e"
- "aca8b5b87", 16),
- "x": int("1c7475da9a161e4b3f7d6b086494063543a979e34b8d7ac4"
- "4204d47bf9f", 16),
- "y": int("131cbd433f112871cc175943991b6a1350bf0cdd57ed8c83"
- "1a2a7710c92", 16),
+ "d": int(
+ "1da7422b50e3ff051f2aaaed10acea6cbf6110c517da2f4e" "aca8b5b87",
+ 16,
+ ),
+ "x": int(
+ "1c7475da9a161e4b3f7d6b086494063543a979e34b8d7ac4"
+ "4204d47bf9f",
+ 16,
+ ),
+ "y": int(
+ "131cbd433f112871cc175943991b6a1350bf0cdd57ed8c83"
+ "1a2a7710c92",
+ 16,
+ ),
},
-
{
"curve": "sect233k1",
- "d": int("530951158f7b1586978c196603c12d25607d2cb0557efadb"
- "23cd0ce8", 16),
- "x": int("d37500a0391d98d3070d493e2b392a2c79dc736c097ed24b"
- "7dd5ddec44", 16),
- "y": int("1d996cc79f37d8dba143d4a8ad9a8a60ed7ea760aae1ddba"
- "34d883f65d9", 16),
+ "d": int(
+ "530951158f7b1586978c196603c12d25607d2cb0557efadb" "23cd0ce8",
+ 16,
+ ),
+ "x": int(
+ "d37500a0391d98d3070d493e2b392a2c79dc736c097ed24b"
+ "7dd5ddec44",
+ 16,
+ ),
+ "y": int(
+ "1d996cc79f37d8dba143d4a8ad9a8a60ed7ea760aae1ddba"
+ "34d883f65d9",
+ 16,
+ ),
},
-
{
"curve": "sect571r1",
- "d": int("1443e93c7ef6802655f641ecbe95e75f1f15b02d2e172f49"
- "a32e22047d5c00ebe1b3ff0456374461360667dbf07bc67f"
- "7d6135ee0d1d46a226a530fefe8ebf3b926e9fbad8d57a6", 16),
- "x": int("53e3710d8e7d4138db0a369c97e5332c1be38a20a4a84c36"
- "f5e55ea9fd6f34545b864ea64f319e74b5ee9e4e1fa1b7c5"
- "b2db0e52467518f8c45b658824871d5d4025a6320ca06f8", 16),
- "y": int("3a22cfd370c4a449b936ae97ab97aab11c57686cca99d14e"
- "f184f9417fad8bedae4df8357e3710bcda1833b30e297d4b"
- "f637938b995d231e557d13f062e81e830af5ab052208ead", 16),
+ "d": int(
+ "1443e93c7ef6802655f641ecbe95e75f1f15b02d2e172f49"
+ "a32e22047d5c00ebe1b3ff0456374461360667dbf07bc67f"
+ "7d6135ee0d1d46a226a530fefe8ebf3b926e9fbad8d57a6",
+ 16,
+ ),
+ "x": int(
+ "53e3710d8e7d4138db0a369c97e5332c1be38a20a4a84c36"
+ "f5e55ea9fd6f34545b864ea64f319e74b5ee9e4e1fa1b7c5"
+ "b2db0e52467518f8c45b658824871d5d4025a6320ca06f8",
+ 16,
+ ),
+ "y": int(
+ "3a22cfd370c4a449b936ae97ab97aab11c57686cca99d14e"
+ "f184f9417fad8bedae4df8357e3710bcda1833b30e297d4b"
+ "f637938b995d231e557d13f062e81e830af5ab052208ead",
+ 16,
+ ),
},
-
{
"curve": "sect571r1",
- "d": int("3d2bd44ca9eeee8c860a4873ed55a54bdfdf5dab4060df72"
- "92877960b85d1fd496aa33c587347213d7f6bf208a6ab4b4"
- "30546e7b6ffbc3135bd12f44a28517867ca3c83a821d6f8", 16),
- "x": int("7a7af10f6617090bade18b2e092d0dfdc87cd616db7f2db1"
- "33477a82bfe3ea421ebb7d6289980819292a719eb2471955"
- "29ea60ad62862de0a26c72bfc49ecc81c2f9ed704e3168f", 16),
- "y": int("721496cf16f988b1aabef3368450441df8439a0ca794170f"
- "270ead56203d675b57f5a4090a3a2f602a77ff3bac1417f7"
- "e25a683f667b3b91f105016a47afad46a0367b18e2bdf0c", 16),
+ "d": int(
+ "3d2bd44ca9eeee8c860a4873ed55a54bdfdf5dab4060df72"
+ "92877960b85d1fd496aa33c587347213d7f6bf208a6ab4b4"
+ "30546e7b6ffbc3135bd12f44a28517867ca3c83a821d6f8",
+ 16,
+ ),
+ "x": int(
+ "7a7af10f6617090bade18b2e092d0dfdc87cd616db7f2db1"
+ "33477a82bfe3ea421ebb7d6289980819292a719eb2471955"
+ "29ea60ad62862de0a26c72bfc49ecc81c2f9ed704e3168f",
+ 16,
+ ),
+ "y": int(
+ "721496cf16f988b1aabef3368450441df8439a0ca794170f"
+ "270ead56203d675b57f5a4090a3a2f602a77ff3bac1417f7"
+ "e25a683f667b3b91f105016a47afad46a0367b18e2bdf0c",
+ 16,
+ ),
},
]
@@ -2414,7 +2800,8 @@ a4090a3a2f602a77ff3bac1417f7e25a683f667b3b91f105016a47afad46a0367b18e2bdf0c
def test_load_fips_ecdsa_signing_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.2
# "SigVer" information for "ecdsa_values"
# Curves/SHAs selected: P-192, B-571,SHA-512
@@ -2481,7 +2868,8 @@ c8341b4a0a657bf6a234d4fe78631c8e07ac1f4dc7474cd6b4545d536b7b17c160db4562d9
bdcf3035f6829ede041b745955d219dc5d30ddd8b37f6ba0f6d2857504cdc68a1ed812a10
S = 34db9998dc53527114518a7ce3783d674ca8cced823fa05e2942e7a0a20b3cc583dcd9\
30c43f9b93079c5ee18a1f5a66e7c3527c18610f9b47a4da7e245ef803e0662e4d2ad721c
- """).splitlines()
+ """
+ ).splitlines()
expected = [
{
@@ -2499,7 +2887,7 @@ bdcf3035f6829ede041b745955d219dc5d30ddd8b37f6ba0f6d2857504cdc68a1ed812a10
"y": int("76fab681d00b414ea636ba215de26d98c41bd7f2e4d65477", 16),
"r": int("6994d962bdd0d793ffddf855ec5bf2f91a9698b46258a63e", 16),
"s": int("02ba6465a234903744ab02bc8521405b73cf5fc00e1a9f41", 16),
- "fail": True
+ "fail": True,
},
{
"curve": "secp192r1",
@@ -2527,22 +2915,37 @@ bdcf3035f6829ede041b745955d219dc5d30ddd8b37f6ba0f6d2857504cdc68a1ed812a10
b"d74e38983b24c0748618e2f92ef7cac257ff4bd1f41113f2891eb13c4793"
b"0e69ddbe91f270fb"
),
- "d": int("3e1b03ffca4399d5b439fac8f87a5cb06930f00d304193d7daf83d59"
- "47d0c1e293f74aef8e56849f16147133c37a6b3d1b1883e5d61d6b87"
- "1ea036c5291d9a74541f28878cb986", 16),
- "x": int("3b236fc135d849d50140fdaae1045e6ae35ef61091e98f5059b30eb1"
- "6acdd0deb2bc0d3544bc3a666e0014e50030134fe5466a9e4d3911ed"
- "580e28851f3747c0010888e819d3d1f", 16),
- "y": int("3a8b6627a587d289032bd76374d16771188d7ff281c39542c8977f68"
- "72fa932e5daa14e13792dea9ffe8e9f68d6b525ec99b81a5a60cfb05"
- "90cc6f297cfff8d7ba1a8bb81fe2e16", 16),
- "r": int("2eb1c5c1fc93cf3c8babed12c031cf1504e094174fd335104cbe4a2a"
- "bd210b5a14b1c3a455579f1ed0517c31822340e4dd3c1f967e1b4b9d"
- "071a1072afc1a199f8c548cd449a634", 16),
- "s": int("22f97bb48641235826cf4e597fa8de849402d6bd6114ad2d7fbcf53a"
- "08247e5ee921f1bd5994dffee36eedff5592bb93b8bb148214da3b7b"
- "aebffbd96b4f86c55b3f6bbac142442", 16),
- "fail": False
+ "d": int(
+ "3e1b03ffca4399d5b439fac8f87a5cb06930f00d304193d7daf83d59"
+ "47d0c1e293f74aef8e56849f16147133c37a6b3d1b1883e5d61d6b87"
+ "1ea036c5291d9a74541f28878cb986",
+ 16,
+ ),
+ "x": int(
+ "3b236fc135d849d50140fdaae1045e6ae35ef61091e98f5059b30eb1"
+ "6acdd0deb2bc0d3544bc3a666e0014e50030134fe5466a9e4d3911ed"
+ "580e28851f3747c0010888e819d3d1f",
+ 16,
+ ),
+ "y": int(
+ "3a8b6627a587d289032bd76374d16771188d7ff281c39542c8977f68"
+ "72fa932e5daa14e13792dea9ffe8e9f68d6b525ec99b81a5a60cfb05"
+ "90cc6f297cfff8d7ba1a8bb81fe2e16",
+ 16,
+ ),
+ "r": int(
+ "2eb1c5c1fc93cf3c8babed12c031cf1504e094174fd335104cbe4a2a"
+ "bd210b5a14b1c3a455579f1ed0517c31822340e4dd3c1f967e1b4b9d"
+ "071a1072afc1a199f8c548cd449a634",
+ 16,
+ ),
+ "s": int(
+ "22f97bb48641235826cf4e597fa8de849402d6bd6114ad2d7fbcf53a"
+ "08247e5ee921f1bd5994dffee36eedff5592bb93b8bb148214da3b7b"
+ "aebffbd96b4f86c55b3f6bbac142442",
+ 16,
+ ),
+ "fail": False,
},
{
"curve": "sect571r1",
@@ -2554,28 +2957,44 @@ bdcf3035f6829ede041b745955d219dc5d30ddd8b37f6ba0f6d2857504cdc68a1ed812a10
b"0f10bc31c249b7b46edd2462a55f85560d99bde9d5b06b97817d1dbe0a67"
b"c701d6e6e7878272"
),
- "d": int("2e09ffd8b434bb7f67d1d3ccf482164f1653c6e4ec64dec2517aa21b"
- "7a93b2b21ea1eebb54734882f29303e489f02e3b741a87287e2dcdf3"
- "858eb6d2ec668f8b5b26f442ce513a2", 16),
- "x": int("36f1be8738dd7dae4486b86a08fe90424f3673e76b10e739442e15f3"
- "bfafaf841842ac98e490521b7e7bb94c127529f6ec6a42cc6f06fc80"
- "606f1210fe020ff508148f93301c9d3", 16),
- "y": int("4d39666ebe99fe214336ad440d776c88eb916f2f4a3433548b87d2ae"
- "bed840b424d15c8341b4a0a657bf6a234d4fe78631c8e07ac1f4dc74"
- "74cd6b4545d536b7b17c160db4562d9", 16),
- "r": int("3d8105f87fe3166046c08e80a28acc98a80b8b7a729623053c2a9e80"
- "afd06756edfe09bdcf3035f6829ede041b745955d219dc5d30ddd8b3"
- "7f6ba0f6d2857504cdc68a1ed812a10", 16),
- "s": int("34db9998dc53527114518a7ce3783d674ca8cced823fa05e2942e7a0"
- "a20b3cc583dcd930c43f9b93079c5ee18a1f5a66e7c3527c18610f9b"
- "47a4da7e245ef803e0662e4d2ad721c", 16)
- }
+ "d": int(
+ "2e09ffd8b434bb7f67d1d3ccf482164f1653c6e4ec64dec2517aa21b"
+ "7a93b2b21ea1eebb54734882f29303e489f02e3b741a87287e2dcdf3"
+ "858eb6d2ec668f8b5b26f442ce513a2",
+ 16,
+ ),
+ "x": int(
+ "36f1be8738dd7dae4486b86a08fe90424f3673e76b10e739442e15f3"
+ "bfafaf841842ac98e490521b7e7bb94c127529f6ec6a42cc6f06fc80"
+ "606f1210fe020ff508148f93301c9d3",
+ 16,
+ ),
+ "y": int(
+ "4d39666ebe99fe214336ad440d776c88eb916f2f4a3433548b87d2ae"
+ "bed840b424d15c8341b4a0a657bf6a234d4fe78631c8e07ac1f4dc74"
+ "74cd6b4545d536b7b17c160db4562d9",
+ 16,
+ ),
+ "r": int(
+ "3d8105f87fe3166046c08e80a28acc98a80b8b7a729623053c2a9e80"
+ "afd06756edfe09bdcf3035f6829ede041b745955d219dc5d30ddd8b3"
+ "7f6ba0f6d2857504cdc68a1ed812a10",
+ 16,
+ ),
+ "s": int(
+ "34db9998dc53527114518a7ce3783d674ca8cced823fa05e2942e7a0"
+ "a20b3cc583dcd930c43f9b93079c5ee18a1f5a66e7c3527c18610f9b"
+ "47a4da7e245ef803e0662e4d2ad721c",
+ 16,
+ ),
+ },
]
assert expected == load_fips_ecdsa_signing_vectors(vector_data)
def test_load_kasvs_dh_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
[SHA(s) supported (Used for hashing Z): SHA256 ]
# Generated on Thu Mar 17 20:44:26 2011
@@ -2745,70 +3164,83 @@ c5ee6e890b14516419110f5252ff1cceea8e274b2987aa78e3bae90c1935b276b7a1f1c944f79d\
d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
CAVSHashZZ = 17dbbaa7a20c1390cd8cb3d31ee947bf9dde87739e067b9861ffeea9
Result = P (0 - Correct)
- """).splitlines()
+ """
+ ).splitlines()
expected = [
{
- 'fail_agree': False,
- 'fail_z': False,
- 'g': int(
+ "fail_agree": False,
+ "fail_z": False,
+ "g": int(
"a51883e9ac0539859df3d25c716437008bb4bd8ec4786eb4bc643299daef5"
"e3e5af5863a6ac40a597b83a27583f6a658d408825105b16d31b6ed088fc6"
"23f648fd6d95e9cefcb0745763cddf564c87bcf4ba7928e74fd6a3080481f"
"588d535e4c026b58a21e1e5ec412ff241b436043e29173f1dc6cb943c0974"
- "2de989547288", 16),
- 'p': int(
+ "2de989547288",
+ 16,
+ ),
+ "p": int(
"da3a8085d372437805de95b88b675122f575df976610c6a844de99f1df82a"
"06848bf7a42f18895c97402e81118e01a00d0855d51922f434c022350861d"
"58ddf60d65bc6941fc6064b147071a4c30426d82fc90d888f94990267c64b"
"eef8c304a4b2b26fb93724d6a9472fa16bc50c5b9b8b59afb62cfe9ea3ba0"
- "42c73a6ade35", 16),
- 'q': 1386090807861091316803998193774751098153687863463,
- 'x1': 381229709512864262422021151581620734547375903702,
- 'x2': 479735944608461101114916716909067001453470352916,
- 'y1': int(
+ "42c73a6ade35",
+ 16,
+ ),
+ "q": 1386090807861091316803998193774751098153687863463,
+ "x1": 381229709512864262422021151581620734547375903702,
+ "x2": 479735944608461101114916716909067001453470352916,
+ "y1": int(
"5a7890f6d20ee9c7162cd84222cb0c7cb5b4f29244a58fc95327fc41045f4"
"76fb3da42fca76a1dd59222a7a7c3872d5af7d8dc254e003eccdb38f29161"
"9c51911df2b6ed67d0b459f4bc25819c0078777b9a1a24c72e7c037a3720a"
"1edad5863ef5ac75ce816869c820859558d5721089ddbe331f55bef741396"
- "a3bbf85c6c1a", 16),
- 'y2': int(
+ "a3bbf85c6c1a",
+ 16,
+ ),
+ "y2": int(
"b92af0468b841ea5de4ca91d895b5e922245421de57ed7a88d2de41610b20"
"8e8e233705f17b2e9eb91914bad2fa87f0a58519a7da2980bc06e7411c925"
"a6050526bd86e621505e6f610b63fdcd9afcfaa96bd087afca44d9197cc35"
"b559f731357a5b979250c0f3a254bb8165f5072156e3fd6f9a6e69bcf4b45"
- "78f78b3bde7", 16),
- 'z': binascii.unhexlify(
+ "78f78b3bde7",
+ 16,
+ ),
+ "z": binascii.unhexlify(
b"8d8f4175e16e15a42eb9099b11528af88741cc206a088971d3064bb291ed"
b"a608d1600bff829624db258fd15e95d96d3e74c6be3232afe5c855b9c596"
b"81ce13b7aea9ff2b16707e4c02f0e82bf6dadf2149ac62630f6c62dea0e5"
b"05e3279404da5ffd5a088e8474ae0c8726b8189cb3d2f04baffe700be849"
b"df9f91567fc2ebb8"
- )
+ ),
},
{
- 'fail_agree': False,
- 'fail_z': False,
- 'g': int(
+ "fail_agree": False,
+ "fail_z": False,
+ "g": int(
"a51883e9ac0539859df3d25c716437008bb4bd8ec4786eb4bc643299daef5"
"e3e5af5863a6ac40a597b83a27583f6a658d408825105b16d31b6ed088fc6"
"23f648fd6d95e9cefcb0745763cddf564c87bcf4ba7928e74fd6a3080481f"
"588d535e4c026b58a21e1e5ec412ff241b436043e29173f1dc6cb943c0974"
- "2de989547288", 16),
- 'p': int(
+ "2de989547288",
+ 16,
+ ),
+ "p": int(
"da3a8085d372437805de95b88b675122f575df976610c6a844de99f1df82a"
"06848bf7a42f18895c97402e81118e01a00d0855d51922f434c022350861d"
"58ddf60d65bc6941fc6064b147071a4c30426d82fc90d888f94990267c64b"
"eef8c304a4b2b26fb93724d6a9472fa16bc50c5b9b8b59afb62cfe9ea3ba0"
- "42c73a6ade35", 16),
- 'q': 1386090807861091316803998193774751098153687863463,
- 'x1': int(
- "32e642683d745a23dccf4f12f989d8dfd1fd9894c422930950cb4c71",
- 16),
- 'x2': int(
- "7d8ae93df3bc09d399a4157ec562126acf51092c3269ab27f60a3a2b",
- 16),
- 'y1': int(
+ "42c73a6ade35",
+ 16,
+ ),
+ "q": 1386090807861091316803998193774751098153687863463,
+ "x1": int(
+ "32e642683d745a23dccf4f12f989d8dfd1fd9894c422930950cb4c71", 16
+ ),
+ "x2": int(
+ "7d8ae93df3bc09d399a4157ec562126acf51092c3269ab27f60a3a2b", 16
+ ),
+ "y1": int(
"8cd371363b32fcc2e936e345f2278b77001f2efdf78512c3ee75c12f88507"
"e2d5c0e5cdded3bb78435506c8028a3f4d6f028c0f49a0d61f1285795197e"
"56deac80279e723f2b3746e213ac8ec60f1cefc2308ff17a7e9e2efab537e"
@@ -2817,8 +3249,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"3e1c450c5798dc05f8265ad9e35095ff112af9e889f00315fa337a76a4506"
"70866eca12cc6ad0778576962eb9cdc12721d3c15e4d87b67488a145d4002"
"40670eb26695a42879cd3940a55087f6527667277e1212a202dbe455c45c6"
- "4b9be4a38153557bbb8fd755", 16),
- 'y2': int(
+ "4b9be4a38153557bbb8fd755",
+ 16,
+ ),
+ "y2": int(
"22127e9728e906ea4b1512c8b1e80474b58446210c23ccfc800f83c2c15da"
"8159940e494b235266f6a9d5f80529067794f1a9edd566755d23d0a3060fe"
"074c5a10122df3e472973bba39ea3a988e8387f5f0491e590b6b5edc299b4"
@@ -2827,8 +3261,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"6c3d75d9bcf83f4b8d1ed39408bd8d973b4ea81e8e832eac361dcd5307133"
"88a60971ea9f8b1e69c1e99df1cca12bdaf293dacfa1419c5692ceffa9198"
"8aef3321ac8cbc2efae6c4337c8808310fb5a240395a98e6004fe613c39e8"
- "4f4177341746d9e388dcb2e8", 16),
- 'z': binascii.unhexlify(
+ "4f4177341746d9e388dcb2e8",
+ 16,
+ ),
+ "z": binascii.unhexlify(
b"0efeaa399a182e0a603baf0dd95aa0fae5289ebd47d5f0f60c86bc936839"
b"c31c9f7f37bf04f76ab02f4094a8ab10ed907ec7291585cc085c3e8981df"
b"2bd46a01c19ec9a2f66709df1d4fefbeb48c8263554e46890f59eb642bf9"
@@ -2838,31 +3274,35 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
b"ce2a585eb9e8f308b48cf4e29593b6f7a02e8625e1e8bff1ea1405f8c8c3"
b"4b8339a9a99c7c9de4eb9895df7719ccda9394f53080eff1226f6b9c7ae0"
b"a38941e18b1a137aabbb62308eb35ba2"
- )
+ ),
},
{
- 'fail_agree': False,
- 'fail_z': True,
- 'g': int(
+ "fail_agree": False,
+ "fail_z": True,
+ "g": int(
"a51883e9ac0539859df3d25c716437008bb4bd8ec4786eb4bc643299daef5"
"e3e5af5863a6ac40a597b83a27583f6a658d408825105b16d31b6ed088fc6"
"23f648fd6d95e9cefcb0745763cddf564c87bcf4ba7928e74fd6a3080481f"
"588d535e4c026b58a21e1e5ec412ff241b436043e29173f1dc6cb943c0974"
- "2de989547288", 16),
- 'p': int(
+ "2de989547288",
+ 16,
+ ),
+ "p": int(
"da3a8085d372437805de95b88b675122f575df976610c6a844de99f1df82a"
"06848bf7a42f18895c97402e81118e01a00d0855d51922f434c022350861d"
"58ddf60d65bc6941fc6064b147071a4c30426d82fc90d888f94990267c64b"
"eef8c304a4b2b26fb93724d6a9472fa16bc50c5b9b8b59afb62cfe9ea3ba0"
- "42c73a6ade35", 16),
- 'q': 1386090807861091316803998193774751098153687863463,
- 'x1': int(
- "66502429aba271e2f2ee2197a2b336e5f0467f192aa28b60dcbf1194",
- 16),
- 'x2': int(
- "106b358be4f068348ac240ecbb454e5c39ca80b078cb0fafd856e9c5",
- 16),
- 'y1': int(
+ "42c73a6ade35",
+ 16,
+ ),
+ "q": 1386090807861091316803998193774751098153687863463,
+ "x1": int(
+ "66502429aba271e2f2ee2197a2b336e5f0467f192aa28b60dcbf1194", 16
+ ),
+ "x2": int(
+ "106b358be4f068348ac240ecbb454e5c39ca80b078cb0fafd856e9c5", 16
+ ),
+ "y1": int(
"dfb001294215423d7146a2453cdb8598ccef01e1d931a913c3e4ed4a3cf38"
"a912066c28e4eaf77dd80ff07183a6160bd95932f513402f864dcf7a70cbe"
"dc9b60bbfbc67f72a83d5f6463a2b5a4fc906d3e921f5e1069126113265b4"
@@ -2871,8 +3311,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"51043d351bb74a952e6a694e6e7456f714c47d7c8eeeb4fd83ad93c86b784"
"45f9393fdfd65c7dbd7fd6eba9794ddf183901b1d213321fd0ab3f7588ab0"
"f6b3692f365a87131eda0e062505861988f6ce63150207545ecf9678e0971"
- "330253dfb7cfd546c5346fec", 16),
- 'y2': int(
+ "330253dfb7cfd546c5346fec",
+ 16,
+ ),
+ "y2": int(
"715d0781975b7b03162f4401c1eda343fd9bf1140006034573b31828a618c"
"356163554cd27da956f7179a69e860fb6efeaa2e2aa9f1261506a8344c492"
"9953621381b13d6426e152c0f2f94bfcd2b758eca24923596d427ed8f957e"
@@ -2881,8 +3323,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"ad5c5bd490ea600e04379232fb1077fbf394f4579accdbe352714e25b8891"
"6dca8d8f7e0c4ed9594f7693f656a235a2e88ebda48b0d557e32da9f12d2a"
"4c3180f05b16b4fba9bec79278a3971b77f9223b5ab78b857e0376c500821"
- "1592c8c72d521373ee3b22b8", 16),
- 'z': binascii.unhexlify(
+ "1592c8c72d521373ee3b22b8",
+ 16,
+ ),
+ "z": binascii.unhexlify(
b"cf879ebd107bb877457809c3fc410218b7acba3c5967495a8f1c3370d57f"
b"038a48dd69f9f69b9f4dd855e7c58a1e4ec32646a978266eb314db468ea1"
b"dfcee8a85a1644a5732498c4fbcdf85098c6ed0ce12e431e99142fd23353"
@@ -2892,12 +3336,12 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
b"665095490056287e4fc49e6cb3181cb2bf06444fd0040150271c9ce1f61c"
b"13ecd5dd022194a2dbf3e1c7fbc6bd19497c7b888b4da613d28fa6f378a4"
b"3369cb8795a1c823f7d6cf4d84bba578"
- )
+ ),
},
{
- 'fail_agree': True,
- 'fail_z': False,
- 'g': int(
+ "fail_agree": True,
+ "fail_z": False,
+ "g": int(
"35513ec441402b78353ab1bba550b21c76c89973885a627170262ef52497d"
"5d137b8927a212aaab2f051198c90bb81dffd9eb10b36b7ca3b63565b4c10"
"25aea3b5e9c4a348c9cfa17f3907a1e4469701c0dedb8a4b9e96c5965b1fb"
@@ -2906,8 +3350,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"65bb4e1e9474993fe382fd23480dc875861be152997a621fdb7aef977ea5b"
"4d3d74486b162dc28f95a64cf65587a919a57eef92934fc9410df7f09fa82"
"f975328ed82ff29cc3e15a971f56f4ac2dcb289252575e02a6cdb7fcc6cdd"
- "d7b0dca9c422e63eb2b8f05", 16),
- 'p': int(
+ "d7b0dca9c422e63eb2b8f05",
+ 16,
+ ),
+ "p": int(
"f3722b9b911c6aede9eaeeaa406283de66a097f39a7225df6c3c916e57920"
"d356e50478d307dbfd146bfb91b6f68ecbbcf54b3d19c33a4b17293fea3e3"
"d6bff8ac4cca93a805386f062a8a27ae906ef5da94d279fd7b3d7289e0095"
@@ -2916,17 +3362,19 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"3c3dfda8de8429e087c5be97fc5c9db9526031ad3a218bd9916fb4a3c2796"
"6d208b1e360014c01e95530c148fb3cd27e6a7250d3c3b81dcd220ca14548"
"dbccf99ebb9e334db6bcd14e632c98dd3f9860af7ae450f1b7809b45f0ec1"
- "0e6f27672beebc9963befc73", 16),
- 'q': int(
- "a9a17de95a29091bf8e07dab53ea1aba9403be3c61027c6c8f48bac5",
- 16),
- 'x1': int(
- "1610eaa4e0ccc8857e2b53149e008492b1fbd9025a6e8d95aaee9c0f",
- 16),
- 'x2': int(
- "c4c83d75b27864b052cadc556e500e25aabf0c9d1bc01f0e1fe3862",
- 16),
- 'y1': int(
+ "0e6f27672beebc9963befc73",
+ 16,
+ ),
+ "q": int(
+ "a9a17de95a29091bf8e07dab53ea1aba9403be3c61027c6c8f48bac5", 16
+ ),
+ "x1": int(
+ "1610eaa4e0ccc8857e2b53149e008492b1fbd9025a6e8d95aaee9c0f", 16
+ ),
+ "x2": int(
+ "c4c83d75b27864b052cadc556e500e25aabf0c9d1bc01f0e1fe3862", 16
+ ),
+ "y1": int(
"51ee21cd9f97015180f258fad5c94ff5a458806b1412087236bf77fe87aae"
"1a36735816ed6e2160a731159814b6ae1f3f52c478dd9207094adfb62f766"
"7d5c366327e66d23096395e938504db330953a708015f861fe9d948761109"
@@ -2935,8 +3383,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"a6f14ccdb29db02f64911bd83bfdcdfc843dd14a4cab9acb0bda8b293d2f5"
"f7050768e57533cbc415a29e6f31cc365e107f91ae3722484e2c7329a85af"
"69055a5a104da37e810878896d1b247b02b75234ecff82b1958f42d7b0316"
- "22e9394c98b5229112f7f620", 16),
- 'y2': int(
+ "22e9394c98b5229112f7f620",
+ 16,
+ ),
+ "y2": int(
"467a857337a82472a1307a64dccc8e9994c5c63ec4312936885d17be41905"
"1a5f037fbb052d7010ebe01634d9e8b8b522d9ab4749fdc274f465369b89e"
"360df8f70b7865a3c71d2dbcd2df19e9293dab1153d3d63fcb7deb559b684"
@@ -2945,8 +3395,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"c193f460dcd0be7e6e06e546da7653770dc5859df87029e722dbe81361030"
"569148d1636988926bf0dcfe47c9d8a54698c08b3b5c70afe86b5c6f64346"
"3f8f34889d27d6cfd2d478c2d7b3d008a985c7380f0b43f10024b59c35438"
- "80883c42d0e7e0a07326ba3a", 16),
- 'z': binascii.unhexlify(
+ "80883c42d0e7e0a07326ba3a",
+ 16,
+ ),
+ "z": binascii.unhexlify(
b"10a30bacab82e652415376baffdbc008c7eb2e5a3aa68bc10ce486ca8498"
b"3fd89b1b027bb40e75333406361005f5e756526a95fe01202df9217d81b1"
b"713d5187c368fdd4c9c2433d9e6c18844769479b725c4140c92a304ee1bc"
@@ -2956,41 +3408,47 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
b"68c90178974a0602436cd186748bcc63a629edc3a0db59415cccd37a6513"
b"0ea477c89da92d41371f5972891cf41f9c7f0e75ccbff9893225384db30d"
b"aa5e310f08e3e0fad98bcdf8ecf35fe5"
- )
+ ),
},
{
- 'fail_agree': False,
- 'fail_z': False,
- 'g': int("35513ec441402b78353ab1bba550b21c76c89973885a627170262ef5"
- "2497d5d137b8927a212aaab2f051198c90bb81dffd9eb10b36b7ca3b"
- "63565b4c1025aea3b5e9c4a348c9cfa17f3907a1e4469701c0dedb8a"
- "4b9e96c5965b1fb8c229b0c34baac774bf9dda4fc5ee8764358b3c84"
- "812878aab7464bc09e97aecab7d7e3fbb4870e2a3b89667a4158bf1e"
- "d1a90dfaf47019fbb52b1b96365bb4e1e9474993fe382fd23480dc87"
- "5861be152997a621fdb7aef977ea5b4d3d74486b162dc28f95a64cf6"
- "5587a919a57eef92934fc9410df7f09fa82f975328ed82ff29cc3e15"
- "a971f56f4ac2dcb289252575e02a6cdb7fcc6cddd7b0dca9c422e63e"
- "b2b8f05", 16),
- 'p': int("f3722b9b911c6aede9eaeeaa406283de66a097f39a7225df6c3c916e"
- "57920d356e50478d307dbfd146bfb91b6f68ecbbcf54b3d19c33a4b1"
- "7293fea3e3d6bff8ac4cca93a805386f062a8a27ae906ef5da94d279"
- "fd7b3d7289e00956f76bae9c0d2b8d11742ca5809630632aae58f9c6"
- "dce00c7380581deffde2187b022f83c6ceaeaadb0844a17fcbb04039"
- "ca6843c91f0c9058b22434b263c3dfda8de8429e087c5be97fc5c9db"
- "9526031ad3a218bd9916fb4a3c27966d208b1e360014c01e95530c14"
- "8fb3cd27e6a7250d3c3b81dcd220ca14548dbccf99ebb9e334db6bcd"
- "14e632c98dd3f9860af7ae450f1b7809b45f0ec10e6f27672beebc99"
- "63befc73", 16),
- 'q': int(
- "a9a17de95a29091bf8e07dab53ea1aba9403be3c61027c6c8f48bac5",
- 16),
- 'x1': int(
- "9ee22ac51664e40e0a24dbb94142dba40605e2b6eeaaa0268a0f6847",
- 16),
- 'x2': int(
- "438093a468236658821bf64eb08456139963d4fb27121c3ed6c55876",
- 16),
- 'y1': int(
+ "fail_agree": False,
+ "fail_z": False,
+ "g": int(
+ "35513ec441402b78353ab1bba550b21c76c89973885a627170262ef5"
+ "2497d5d137b8927a212aaab2f051198c90bb81dffd9eb10b36b7ca3b"
+ "63565b4c1025aea3b5e9c4a348c9cfa17f3907a1e4469701c0dedb8a"
+ "4b9e96c5965b1fb8c229b0c34baac774bf9dda4fc5ee8764358b3c84"
+ "812878aab7464bc09e97aecab7d7e3fbb4870e2a3b89667a4158bf1e"
+ "d1a90dfaf47019fbb52b1b96365bb4e1e9474993fe382fd23480dc87"
+ "5861be152997a621fdb7aef977ea5b4d3d74486b162dc28f95a64cf6"
+ "5587a919a57eef92934fc9410df7f09fa82f975328ed82ff29cc3e15"
+ "a971f56f4ac2dcb289252575e02a6cdb7fcc6cddd7b0dca9c422e63e"
+ "b2b8f05",
+ 16,
+ ),
+ "p": int(
+ "f3722b9b911c6aede9eaeeaa406283de66a097f39a7225df6c3c916e"
+ "57920d356e50478d307dbfd146bfb91b6f68ecbbcf54b3d19c33a4b1"
+ "7293fea3e3d6bff8ac4cca93a805386f062a8a27ae906ef5da94d279"
+ "fd7b3d7289e00956f76bae9c0d2b8d11742ca5809630632aae58f9c6"
+ "dce00c7380581deffde2187b022f83c6ceaeaadb0844a17fcbb04039"
+ "ca6843c91f0c9058b22434b263c3dfda8de8429e087c5be97fc5c9db"
+ "9526031ad3a218bd9916fb4a3c27966d208b1e360014c01e95530c14"
+ "8fb3cd27e6a7250d3c3b81dcd220ca14548dbccf99ebb9e334db6bcd"
+ "14e632c98dd3f9860af7ae450f1b7809b45f0ec10e6f27672beebc99"
+ "63befc73",
+ 16,
+ ),
+ "q": int(
+ "a9a17de95a29091bf8e07dab53ea1aba9403be3c61027c6c8f48bac5", 16
+ ),
+ "x1": int(
+ "9ee22ac51664e40e0a24dbb94142dba40605e2b6eeaaa0268a0f6847", 16
+ ),
+ "x2": int(
+ "438093a468236658821bf64eb08456139963d4fb27121c3ed6c55876", 16
+ ),
+ "y1": int(
"c2630c9d38ed5c825d1c6a3eba7143f3fc8a049c8bcd1efc212d2af64eca9"
"94308208691d330aa8f27fc4a1e55de4e512113996d21375a667f8c26d76d"
"ee2f6809b15432a33fb735aca5c2263940f58712bded08f55443dee300b94"
@@ -2999,8 +3457,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"d43c4ffc9a605addbdcce0cb3790c6db846156bb857a7b3df40dc6ed04d19"
"cc9eaebb6bbc034e77c3d882a1a62317cce25b6130f0803e3bc49b5e36768"
"260073a617034872be0b50bed32740224beaf582d67fbcfef3b3ecc18f9c7"
- "1c782e9a68495ef31dc7986e", 16),
- 'y2': int(
+ "1c782e9a68495ef31dc7986e",
+ 16,
+ ),
+ "y2": int(
"e192da8e1244e27221c1765344a5bb379dce741d427a734b4bdb6c4d16b24"
"90bd37564d745008e63ae46ef332331d79887ac63298ce143e125f8b320c0"
"f859b7f5f2c1e0053e4a7a16997e6143ff702300c9863ae7caef5c1dfca0e"
@@ -3009,8 +3469,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
"a56431cd48579bf53c903bbe066dd78b23c0996ef3a880f0d91315104366a"
"82f01abdecce96fd371f94e8420f8bc5b896c801df573554f749b03d0d28b"
"1e1a990bc61c7e9659342ac7e268e9c0b7c40fdaab394f29cf0a54f780022"
- "f9a03b0bd28eb7db8b0b1b47", 16),
- 'z': binascii.unhexlify(
+ "f9a03b0bd28eb7db8b0b1b47",
+ 16,
+ ),
+ "z": binascii.unhexlify(
b"56f8f40fa4b8f3580f9014b30d60a42933a53a62182a690142f458dc275c"
b"3b2f0e721bc5ee6e890b14516419110f5252ff1cceea8e274b2987aa78e3"
b"bae90c1935b276b7a1f1c944f79d4774b7a85b3355bdf25cb02bddfbda4e"
@@ -3020,8 +3482,8 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93
b"b75d049d4c82097af8a5ce353e14416b3eeb31ba9bc4f6f3dbd846c5299f"
b"b5c0043a1b95b9149b39d14df9e6a69547abf8a4d518475576730ed52877"
b"9366568e46b7dd4ed787cb72d0733c93"
- )
- }
+ ),
+ },
]
assert expected == load_kasvs_dh_vectors(vector_data)
@@ -3032,7 +3494,8 @@ def test_load_kasvs_ecdh_vectors_empty_vector_data():
def test_load_kasvs_ecdh_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.0
# Parameter set(s) supported: EA EB EC ED EE
# CAVSid: CAVSid (in hex: 434156536964)
@@ -3183,148 +3646,291 @@ f47021022a6c9b45ed791d09d9540eb81ea065fc1959eca365001ee39928c343d75
- """).splitlines()
+ """
+ ).splitlines()
expected = [
- {'errno': 0,
- 'fail': False,
- 'COUNT': 0,
- 'CAVS': {
- 'd': int("f70c297a683d6b7ef82b5af7349606c4447c8b4fc6fa5e80", 16),
- 'x': int("f7b5061fb557e516c50abf541d97dbfd76ca7172b22cf590", 16),
- 'y': int("135e15e21f9e85c76205fd148a92ac19f9e6243ddab322d1", 16)},
- 'IUT': {
- 'd': int("a5b4bbad57f101ca48021cb7440cd681a9d40cd51b99d917", 16),
- 'x': int("79a77fcb18a32cdb59ed5d87740f29e8565d649dbf01ce86", 16),
- 'y': int("f7187efaa0b1573f1fb00905d46810b880bf738b4c720bb7", 16)},
- 'Z': int("26382468d721761e14a87dc3bee67340095c6455962d1ba3", 16),
- 'curve': 'secp192r1'},
-
- {'errno': 8,
- 'fail': True,
- 'COUNT': 2,
- 'CAVS': {
- 'd': int("5f909dcb0ccce58c82fada748c47297579e6a981b5518a96", 16),
- 'x': int("537f1ecfda0e366de393a9bc8188fcc280311bffefe21ecf", 16),
- 'y': int("a1fa1f98498d65f2754caff4e5303a4066a5ff89fde95381", 16)},
- 'IUT': {
- 'd': int("3357aa7f47f3e09421602cc12cdce4434c68e330d44de05e", 16),
- 'x': int("6a33d43d9c72173eabc7a771a5687748c4774c62762e96ec", 16),
- 'y': int("8033f238b3abc69470aad4be8dbe4f60a2fd50207626c56a", 16)},
- 'Z': int("3153034f6617326f19c35be8c99a0585431adf09d2f8e0fd", 16),
- 'curve': 'secp192r1'},
-
- {'errno': 13,
- 'fail': False,
- 'COUNT': 8,
- 'CAVS': {
- 'd': int("8fcfaf0524cc868fad20e50410a2205319f1327308d98dc8", 16),
- 'x': int("9b0243d80a9e328738080fb4d46bc450243d0efb7ead0c92", 16),
- 'y': int("ad5bebad7f03849693071537f60ef858cad214123beee7c7", 16)},
- 'IUT': {
- 'd': int("bba95dac90289cb68ca2b006f9757219b70579c299ad7a7d", 16),
- 'x': int("7733dc0cb365cd6312724196b9b4eb491fd4d2e31b9afdb1", 16),
- 'y': int("92ffa3722acc5b94d772258ba2d471b06c0f53f56fcd8662", 16)},
- 'Z': int("0f3c6e4a29a08296ae730f56a1ebf819ea2edfa6f0434e40", 16),
- 'curve': 'secp192r1'},
-
- {'errno': 0,
- 'fail': False,
- 'COUNT': 0,
- 'CAVS': {
- 'd': int("e53a88af7cf8ce6bf13c8b9ad191494e37a6acc1368c71f4"
- "306e39e5", 16),
- 'x': int("3a24217c4b957fea922eec9d9ac52d5cb4b3fcd95efde1e4"
- "fa0dd6e2", 16),
- 'y': int("775b94025a808eb6f4af14ea4b57dca576c35373c6dc198b"
- "15b981df", 16)},
- 'IUT': {
- 'd': int("09f51e302c6a0fe6ff48f34c208c6af91e70f65f88102e6f"
- "cab9af4a", 16),
- 'x': int("c5d5706ccd7424c74fd616e699865af96e56f39adea6aa05"
- "9e5092b5", 16),
- 'y': int("f0729077bb602404d56d2f7e2ba5bb2f383df4a542556788"
- "1ff0165d", 16)},
- 'Z': int("b1259ceedfb663d9515089cf727e7024fb3d86cbcec611b4"
- "ba0b4ab6", 16),
- 'curve': 'secp224r1'},
-
- {'errno': 2,
- 'fail': True,
- 'COUNT': 0,
- 'CAVS': {
- 'd': int("305dfb4a8850cc59280891147baf457bfe5e2bae98457163"
- "4a77dc8d3472fa9b", 16),
- 'x': int("202cb5a224e6c2a84e624094486edf04116c8d68ec1f4a0e"
- "0ed9ee090e1a900b", 16),
- 'y': int("cacf3a5789bb33954be600425d62d9eae5371f90f8816725"
- "8814213e4a4f4b1a", 16)},
- 'IUT': {
- 'd': int("72cc52808f294b64b6f7233c3d2f5d96cc1d29287320e39e"
- "1c151deef0bc14eb", 16),
- 'x': int("49a768c9a4ca56e374f685dd76a461b1016c59dcded2c8d8"
- "cbd9f23ca453831f", 16),
- 'y': int("b1e3bb9b5f12a3b5ae788535d4554bd8c46e0e6130075e4e"
- "437d3854cf8f1c34", 16)},
- 'Z': int("c0147c3c2691b450b5edc08b51aea224d9f4359ff67aab6d"
- "a3146f396dbceaea", 16),
- 'curve': 'secp256r1'},
-
- {'errno': 0,
- 'fail': False,
- 'COUNT': 0,
- 'CAVS': {
- 'd': int("0e5c98ff2d2a3aab14ad0067b60dbe64e4f541ab5bed11c5"
- "a0c55ae1e60b51ff5faaf377837977d80cbfdc33c2ff542b", 16),
- 'x': int("d1bf2ac21637d66d6398aac01dcd56ac6f065fb45d1f6f16"
- "747bab9e9b01b4630b59b20927aea147355bf41838acb482", 16),
- 'y': int("4c9e23f1c5a41647d094086bf4ed31708651f21d996c4778"
- "0688ac10f77deee2e43b5241b6caecd2fd5444bc50472e0e", 16)},
- 'IUT': {
- 'd': int("f865418473e5bf7d2e1bbcd9bd5a9270c003a9dd35e77813"
- "3ca59fcab4bb64fe24d6800e7047bdd033abc8bfa8db35b5", 16),
- 'x': int("32b72ab9b558249dcbc6cbade234f58e4f7aa5d3f6420ea9"
- "9a5f997e8c2a91fb7fd83779d0d2169428683771c745fd1a", 16),
- 'y': int("c749e02a3719bb56bf1dfc4ba3820309c01ab6e84cb29db7"
- "cdd80f127233f5295687f8178f3a8704c1063b84c2ee472f", 16)},
- 'Z': int("a781430e6078a179df3f9ee27cd8fdc6188f161b6c4ccc40"
- "53ef6c6ca6fc222946883a53c06db08f0a020023ced055aa", 16),
- 'curve': 'secp384r1'},
-
- {'errno': 7,
- 'fail': True,
- 'COUNT': 0,
- 'CAVS': {
- 'd': int("0000002fef62381162942889a6094a6bb9ac1f4ddf66d9cd"
- "a9f618232d31b90c50d7da78a47ed91d40cae946898571db"
- "972dc294b109815f38feee9eaac0d5f7c3250728", 16),
- 'x': int("0000004b05ffa025113390797f2736174aa1c784f4dd34e7"
- "64ee40d40e4d2442677ebea3498086c9473e5c92789cbdb0"
- "2bb327bbd61d58690f6a83d9ca73bccbde37dec4", 16),
- 'y': int("0000004da67cffc98070b82af61feba78787efefb13bd810"
- "d80ff92304788e49a4e5b634b3565474a8ecb1615d7b1b77"
- "a7a27875adb73a8a5d8f3f84e5e8b744cda250b0", 16)},
- 'IUT': {
- 'd': int("00000311a5e520e238141527671a38cb6f776d96a9f82ef7"
- "0dffa11dc0895f4060f1abbb9ad6fd259e4a7beaf5f7266e"
- "a1bb45bcbfebfda2705e5c551e710fb1d745f57e", 16),
- 'x': int("0000010ba3778cb2cc965834c0a9593adc6a222692656d65"
- "7fb0d15293edf0ab33762384a96a16fddea7540b7ccbcca4"
- "6ec4ac9bcf95fdb5aa18e158aab4d91981bd733e", 16),
- 'y': int("0000018522df93ddd636e5bc94daecdc600fa241686ec186"
- "34fd30b7cbdfdc9ffba1166ac08df34a31896f6fad191414"
- "929261ebd7187afb72919f8a0c926be37f99c1e5", 16)},
- 'Z': int("01a5e4b31be4b1346e53906b6767b1fe94ec1a8a5abc28fb"
- "6f01518c056959af3bc9335dddab178b52318cc551255993"
- "1b8dc18de0ce810c2c7f15769d7ce70e719c", 16),
- 'curve': 'secp521r1'}
+ {
+ "errno": 0,
+ "fail": False,
+ "COUNT": 0,
+ "CAVS": {
+ "d": int(
+ "f70c297a683d6b7ef82b5af7349606c4447c8b4fc6fa5e80", 16
+ ),
+ "x": int(
+ "f7b5061fb557e516c50abf541d97dbfd76ca7172b22cf590", 16
+ ),
+ "y": int(
+ "135e15e21f9e85c76205fd148a92ac19f9e6243ddab322d1", 16
+ ),
+ },
+ "IUT": {
+ "d": int(
+ "a5b4bbad57f101ca48021cb7440cd681a9d40cd51b99d917", 16
+ ),
+ "x": int(
+ "79a77fcb18a32cdb59ed5d87740f29e8565d649dbf01ce86", 16
+ ),
+ "y": int(
+ "f7187efaa0b1573f1fb00905d46810b880bf738b4c720bb7", 16
+ ),
+ },
+ "Z": int("26382468d721761e14a87dc3bee67340095c6455962d1ba3", 16),
+ "curve": "secp192r1",
+ },
+ {
+ "errno": 8,
+ "fail": True,
+ "COUNT": 2,
+ "CAVS": {
+ "d": int(
+ "5f909dcb0ccce58c82fada748c47297579e6a981b5518a96", 16
+ ),
+ "x": int(
+ "537f1ecfda0e366de393a9bc8188fcc280311bffefe21ecf", 16
+ ),
+ "y": int(
+ "a1fa1f98498d65f2754caff4e5303a4066a5ff89fde95381", 16
+ ),
+ },
+ "IUT": {
+ "d": int(
+ "3357aa7f47f3e09421602cc12cdce4434c68e330d44de05e", 16
+ ),
+ "x": int(
+ "6a33d43d9c72173eabc7a771a5687748c4774c62762e96ec", 16
+ ),
+ "y": int(
+ "8033f238b3abc69470aad4be8dbe4f60a2fd50207626c56a", 16
+ ),
+ },
+ "Z": int("3153034f6617326f19c35be8c99a0585431adf09d2f8e0fd", 16),
+ "curve": "secp192r1",
+ },
+ {
+ "errno": 13,
+ "fail": False,
+ "COUNT": 8,
+ "CAVS": {
+ "d": int(
+ "8fcfaf0524cc868fad20e50410a2205319f1327308d98dc8", 16
+ ),
+ "x": int(
+ "9b0243d80a9e328738080fb4d46bc450243d0efb7ead0c92", 16
+ ),
+ "y": int(
+ "ad5bebad7f03849693071537f60ef858cad214123beee7c7", 16
+ ),
+ },
+ "IUT": {
+ "d": int(
+ "bba95dac90289cb68ca2b006f9757219b70579c299ad7a7d", 16
+ ),
+ "x": int(
+ "7733dc0cb365cd6312724196b9b4eb491fd4d2e31b9afdb1", 16
+ ),
+ "y": int(
+ "92ffa3722acc5b94d772258ba2d471b06c0f53f56fcd8662", 16
+ ),
+ },
+ "Z": int("0f3c6e4a29a08296ae730f56a1ebf819ea2edfa6f0434e40", 16),
+ "curve": "secp192r1",
+ },
+ {
+ "errno": 0,
+ "fail": False,
+ "COUNT": 0,
+ "CAVS": {
+ "d": int(
+ "e53a88af7cf8ce6bf13c8b9ad191494e37a6acc1368c71f4"
+ "306e39e5",
+ 16,
+ ),
+ "x": int(
+ "3a24217c4b957fea922eec9d9ac52d5cb4b3fcd95efde1e4"
+ "fa0dd6e2",
+ 16,
+ ),
+ "y": int(
+ "775b94025a808eb6f4af14ea4b57dca576c35373c6dc198b"
+ "15b981df",
+ 16,
+ ),
+ },
+ "IUT": {
+ "d": int(
+ "09f51e302c6a0fe6ff48f34c208c6af91e70f65f88102e6f"
+ "cab9af4a",
+ 16,
+ ),
+ "x": int(
+ "c5d5706ccd7424c74fd616e699865af96e56f39adea6aa05"
+ "9e5092b5",
+ 16,
+ ),
+ "y": int(
+ "f0729077bb602404d56d2f7e2ba5bb2f383df4a542556788"
+ "1ff0165d",
+ 16,
+ ),
+ },
+ "Z": int(
+ "b1259ceedfb663d9515089cf727e7024fb3d86cbcec611b4" "ba0b4ab6",
+ 16,
+ ),
+ "curve": "secp224r1",
+ },
+ {
+ "errno": 2,
+ "fail": True,
+ "COUNT": 0,
+ "CAVS": {
+ "d": int(
+ "305dfb4a8850cc59280891147baf457bfe5e2bae98457163"
+ "4a77dc8d3472fa9b",
+ 16,
+ ),
+ "x": int(
+ "202cb5a224e6c2a84e624094486edf04116c8d68ec1f4a0e"
+ "0ed9ee090e1a900b",
+ 16,
+ ),
+ "y": int(
+ "cacf3a5789bb33954be600425d62d9eae5371f90f8816725"
+ "8814213e4a4f4b1a",
+ 16,
+ ),
+ },
+ "IUT": {
+ "d": int(
+ "72cc52808f294b64b6f7233c3d2f5d96cc1d29287320e39e"
+ "1c151deef0bc14eb",
+ 16,
+ ),
+ "x": int(
+ "49a768c9a4ca56e374f685dd76a461b1016c59dcded2c8d8"
+ "cbd9f23ca453831f",
+ 16,
+ ),
+ "y": int(
+ "b1e3bb9b5f12a3b5ae788535d4554bd8c46e0e6130075e4e"
+ "437d3854cf8f1c34",
+ 16,
+ ),
+ },
+ "Z": int(
+ "c0147c3c2691b450b5edc08b51aea224d9f4359ff67aab6d"
+ "a3146f396dbceaea",
+ 16,
+ ),
+ "curve": "secp256r1",
+ },
+ {
+ "errno": 0,
+ "fail": False,
+ "COUNT": 0,
+ "CAVS": {
+ "d": int(
+ "0e5c98ff2d2a3aab14ad0067b60dbe64e4f541ab5bed11c5"
+ "a0c55ae1e60b51ff5faaf377837977d80cbfdc33c2ff542b",
+ 16,
+ ),
+ "x": int(
+ "d1bf2ac21637d66d6398aac01dcd56ac6f065fb45d1f6f16"
+ "747bab9e9b01b4630b59b20927aea147355bf41838acb482",
+ 16,
+ ),
+ "y": int(
+ "4c9e23f1c5a41647d094086bf4ed31708651f21d996c4778"
+ "0688ac10f77deee2e43b5241b6caecd2fd5444bc50472e0e",
+ 16,
+ ),
+ },
+ "IUT": {
+ "d": int(
+ "f865418473e5bf7d2e1bbcd9bd5a9270c003a9dd35e77813"
+ "3ca59fcab4bb64fe24d6800e7047bdd033abc8bfa8db35b5",
+ 16,
+ ),
+ "x": int(
+ "32b72ab9b558249dcbc6cbade234f58e4f7aa5d3f6420ea9"
+ "9a5f997e8c2a91fb7fd83779d0d2169428683771c745fd1a",
+ 16,
+ ),
+ "y": int(
+ "c749e02a3719bb56bf1dfc4ba3820309c01ab6e84cb29db7"
+ "cdd80f127233f5295687f8178f3a8704c1063b84c2ee472f",
+ 16,
+ ),
+ },
+ "Z": int(
+ "a781430e6078a179df3f9ee27cd8fdc6188f161b6c4ccc40"
+ "53ef6c6ca6fc222946883a53c06db08f0a020023ced055aa",
+ 16,
+ ),
+ "curve": "secp384r1",
+ },
+ {
+ "errno": 7,
+ "fail": True,
+ "COUNT": 0,
+ "CAVS": {
+ "d": int(
+ "0000002fef62381162942889a6094a6bb9ac1f4ddf66d9cd"
+ "a9f618232d31b90c50d7da78a47ed91d40cae946898571db"
+ "972dc294b109815f38feee9eaac0d5f7c3250728",
+ 16,
+ ),
+ "x": int(
+ "0000004b05ffa025113390797f2736174aa1c784f4dd34e7"
+ "64ee40d40e4d2442677ebea3498086c9473e5c92789cbdb0"
+ "2bb327bbd61d58690f6a83d9ca73bccbde37dec4",
+ 16,
+ ),
+ "y": int(
+ "0000004da67cffc98070b82af61feba78787efefb13bd810"
+ "d80ff92304788e49a4e5b634b3565474a8ecb1615d7b1b77"
+ "a7a27875adb73a8a5d8f3f84e5e8b744cda250b0",
+ 16,
+ ),
+ },
+ "IUT": {
+ "d": int(
+ "00000311a5e520e238141527671a38cb6f776d96a9f82ef7"
+ "0dffa11dc0895f4060f1abbb9ad6fd259e4a7beaf5f7266e"
+ "a1bb45bcbfebfda2705e5c551e710fb1d745f57e",
+ 16,
+ ),
+ "x": int(
+ "0000010ba3778cb2cc965834c0a9593adc6a222692656d65"
+ "7fb0d15293edf0ab33762384a96a16fddea7540b7ccbcca4"
+ "6ec4ac9bcf95fdb5aa18e158aab4d91981bd733e",
+ 16,
+ ),
+ "y": int(
+ "0000018522df93ddd636e5bc94daecdc600fa241686ec186"
+ "34fd30b7cbdfdc9ffba1166ac08df34a31896f6fad191414"
+ "929261ebd7187afb72919f8a0c926be37f99c1e5",
+ 16,
+ ),
+ },
+ "Z": int(
+ "01a5e4b31be4b1346e53906b6767b1fe94ec1a8a5abc28fb"
+ "6f01518c056959af3bc9335dddab178b52318cc551255993"
+ "1b8dc18de0ce810c2c7f15769d7ce70e719c",
+ 16,
+ ),
+ "curve": "secp521r1",
+ },
]
assert expected == load_kasvs_ecdh_vectors(vector_data)
def test_load_kasvs_ecdh_kdf_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# Parameter set(s) supported: EB EC ED EE
# CAVSid: CAVSid (in hex: 434156536964)
# IUTid: In hex: a1b2c3d4e5
@@ -3361,39 +3967,68 @@ def test_load_kasvs_ecdh_kdf_vectors():
ffdfa60dd7
DKM = ad65fa2d12541c3a21f3cd223efb
Result = F (12 - Tag changed )
- """).splitlines()
+ """
+ ).splitlines()
expected = [
- {'errno': 12,
- 'fail': True,
- 'COUNT': 50,
- 'CAVS': {
- 'd': int("540904b67b3716823dd621ed72ad3dbc615887b4f56f910b"
- "78a57199", 16),
- 'x': int("28e5f3a72d8f6b8499dd1bcdfceafcecec68a0d715789bcf"
- "4b55fe15", 16),
- 'y': int("8c8006a7da7c1a19f5328d7e865522b0c0dfb9a29b2c46dc"
- "96590d2a", 16)},
- 'IUT': {
- 'd': int("5e717ae889fc8d67be11c2ebe1a7d3550051448d68a040b2"
- "dee8e327", 16),
- 'x': int("ae7f3db340b647d61713f5374c019f1be2b28573cb6219bb"
- "7b747223", 16),
- 'y': int("800e6bffcf97c15864ec6e5673fb83359b45f89b8a26a27f"
- "6f3dfbff", 16)},
- 'OI': int("a1b2c3d4e5bb7f1b40d14ebd70443393990b574341565369"
- "645b1582daab9cc6c30d61fdcf1cdfc7e9a304651e0fdb", 16),
- 'Z': int("43f23b2c760d686fc99cc008b63aea92f866e224265af60d"
- "2d8ae540", 16),
- 'DKM': int("ad65fa2d12541c3a21f3cd223efb", 16),
- 'curve': 'secp224r1'}
+ {
+ "errno": 12,
+ "fail": True,
+ "COUNT": 50,
+ "CAVS": {
+ "d": int(
+ "540904b67b3716823dd621ed72ad3dbc615887b4f56f910b"
+ "78a57199",
+ 16,
+ ),
+ "x": int(
+ "28e5f3a72d8f6b8499dd1bcdfceafcecec68a0d715789bcf"
+ "4b55fe15",
+ 16,
+ ),
+ "y": int(
+ "8c8006a7da7c1a19f5328d7e865522b0c0dfb9a29b2c46dc"
+ "96590d2a",
+ 16,
+ ),
+ },
+ "IUT": {
+ "d": int(
+ "5e717ae889fc8d67be11c2ebe1a7d3550051448d68a040b2"
+ "dee8e327",
+ 16,
+ ),
+ "x": int(
+ "ae7f3db340b647d61713f5374c019f1be2b28573cb6219bb"
+ "7b747223",
+ 16,
+ ),
+ "y": int(
+ "800e6bffcf97c15864ec6e5673fb83359b45f89b8a26a27f"
+ "6f3dfbff",
+ 16,
+ ),
+ },
+ "OI": int(
+ "a1b2c3d4e5bb7f1b40d14ebd70443393990b574341565369"
+ "645b1582daab9cc6c30d61fdcf1cdfc7e9a304651e0fdb",
+ 16,
+ ),
+ "Z": int(
+ "43f23b2c760d686fc99cc008b63aea92f866e224265af60d" "2d8ae540",
+ 16,
+ ),
+ "DKM": int("ad65fa2d12541c3a21f3cd223efb", 16),
+ "curve": "secp224r1",
+ }
]
assert expected == load_kasvs_ecdh_vectors(vector_data)
def test_load_x963_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 12.0
# 'ANS X9.63-2001' information for sample
@@ -3443,37 +4078,48 @@ a59b4106cf2dbbc0ab2aa8e2efa7b17902d34276951ceccab87f9661c3e8816
d6e4dd2a599acceb3ea54a6217ce0b50eef4f6b40a5c30250a5a8eeee208002267089dbf351f3f\
5022aa9638bf1ee419dea9c4ff745a25ac27bda33ca08bd56dd1a59b4106cf2dbbc0ab2aa8e2ef\
a7b17902d34276951ceccab87f9661c3e8816
- """).splitlines()
+ """
+ ).splitlines()
assert load_x963_vectors(vector_data) == [
- {"hash": "SHA-1", "count": 0,
- "shared_secret_length": 192,
- "Z": "1c7d7b5f0597b03d06a018466ed1a93e30ed4b04dc64ccdd",
- "sharedinfo_length": 0,
- "key_data_length": 128,
- "key_data": "bf71dffd8f4d99223936beb46fee8ccc"},
- {"hash": "SHA-1", "count": 1,
- "shared_secret_length": 192,
- "Z": "5ed096510e3fcf782ceea98e9737993e2b21370f6cda2ab1",
- "sharedinfo_length": 0,
- "key_data_length": 128,
- "key_data": "ec3e224446bfd7b3be1df404104af953"},
- {"hash": "SHA-512", "count": 0,
- "shared_secret_length": 521,
- "Z": "00aa5bb79b33e389fa58ceadc047197f14e73712f452caa9fc4c9adb369348b\
+ {
+ "hash": "SHA-1",
+ "count": 0,
+ "shared_secret_length": 192,
+ "Z": "1c7d7b5f0597b03d06a018466ed1a93e30ed4b04dc64ccdd",
+ "sharedinfo_length": 0,
+ "key_data_length": 128,
+ "key_data": "bf71dffd8f4d99223936beb46fee8ccc",
+ },
+ {
+ "hash": "SHA-1",
+ "count": 1,
+ "shared_secret_length": 192,
+ "Z": "5ed096510e3fcf782ceea98e9737993e2b21370f6cda2ab1",
+ "sharedinfo_length": 0,
+ "key_data_length": 128,
+ "key_data": "ec3e224446bfd7b3be1df404104af953",
+ },
+ {
+ "hash": "SHA-512",
+ "count": 0,
+ "shared_secret_length": 521,
+ "Z": "00aa5bb79b33e389fa58ceadc047197f14e73712f452caa9fc4c9adb369348b\
81507392f1a86ddfdb7c4ff8231c4bd0f44e44a1b55b1404747a9e2e753f55ef05a2d",
- "sharedinfo_length": 128,
- "sharedinfo": "e3b5b4c1b0d5cf1d2b3a2f9937895d31",
- "key_data_length": 1024,
- "key_data": "4463f869f3cc18769b52264b0112b5858f7ad32a5a2d96d8cffabf7f\
+ "sharedinfo_length": 128,
+ "sharedinfo": "e3b5b4c1b0d5cf1d2b3a2f9937895d31",
+ "key_data_length": 1024,
+ "key_data": "4463f869f3cc18769b52264b0112b5858f7ad32a5a2d96d8cffabf7f\
a733633d6e4dd2a599acceb3ea54a6217ce0b50eef4f6b40a5c30250a5a8eeee208002267089db\
f351f3f5022aa9638bf1ee419dea9c4ff745a25ac27bda33ca08bd56dd1a59b4106cf2dbbc0ab2\
-aa8e2efa7b17902d34276951ceccab87f9661c3e8816"},
+aa8e2efa7b17902d34276951ceccab87f9661c3e8816",
+ },
]
def test_load_kbkdf_vectors():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 14.4
# "SP800-108 - KDF" information for "test1"
# KDF Mode Supported: Counter Mode
@@ -3523,50 +4169,58 @@ b5730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a7
instring = 7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43aa1b91eeb5\
730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a701
KO = b8894c6133a46701909b5c8a84322dec
- """).splitlines()
+ """
+ ).splitlines()
assert load_nist_kbkdf_vectors(vector_data) == [
- {'prf': 'hmac_sha1',
- 'ctrlocation': 'before_fixed',
- 'rlen': 8,
- 'l': 128,
- 'ki': b'00a39bd547fb88b2d98727cf64c195c61e1cad6c',
- 'fixedinputdatabytelen': b'60',
- 'fixedinputdata': b'98132c1ffaf59ae5cbc0a3133d84c551bb97e0c75ecaddfc\
-30056f6876f59803009bffc7d75c4ed46f40b8f80426750d15bc1ddb14ac5dcb69a68242',
- 'binary rep of i': b'01',
- 'instring': b'0198132c1ffaf59ae5cbc0a3133d84c551bb97e0c75ecaddfc3005\
-6f6876f59803009bffc7d75c4ed46f40b8f80426750d15bc1ddb14ac5dcb69a68242',
- 'ko': b'0611e1903609b47ad7a5fc2c82e47702'},
- {'prf': 'hmac_sha1',
- 'ctrlocation': 'before_fixed',
- 'rlen': 8,
- 'l': 128,
- 'ki': b'a39bdf744ed7e33fdec060c8736e9725179885a8',
- 'fixedinputdatabytelen': b'60',
- 'fixedinputdata': b'af71b44940acff98949ad17f1ca20e8fdb3957cacdcd41e9\
-c591e18235019f90b9f8ee6e75700bcab2f8407525a104799b3e9725e27d738a9045e832',
- 'binary rep of i': b'01',
- 'instring': b'01af71b44940acff98949ad17f1ca20e8fdb3957cacdcd41e9c591\
-e18235019f90b9f8ee6e75700bcab2f8407525a104799b3e9725e27d738a9045e832',
- 'ko': b'51dc4668947e3685099bc3b5f8527468'},
- {'prf': 'hmac_sha224',
- 'ctrlocation': 'after_fixed',
- 'rlen': 8,
- 'l': 128,
- 'ki': b'ab56556b107a3a79fe084df0f1bb3ad049a6cc1490f20da4b3df282c',
- 'fixedinputdatabytelen': b'60',
- 'fixedinputdata': b'7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43\
-aa1b91eeb5730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a7',
- 'binary rep of i': b'01',
- 'instring': b'7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43aa1b91\
-eeb5730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a701',
- 'ko': b'b8894c6133a46701909b5c8a84322dec'}
+ {
+ "prf": "hmac_sha1",
+ "ctrlocation": "before_fixed",
+ "rlen": 8,
+ "l": 128,
+ "ki": b"00a39bd547fb88b2d98727cf64c195c61e1cad6c",
+ "fixedinputdatabytelen": b"60",
+ "fixedinputdata": b"98132c1ffaf59ae5cbc0a3133d84c551bb97e0c75ecaddfc\
+30056f6876f59803009bffc7d75c4ed46f40b8f80426750d15bc1ddb14ac5dcb69a68242",
+ "binary rep of i": b"01",
+ "instring": b"0198132c1ffaf59ae5cbc0a3133d84c551bb97e0c75ecaddfc3005\
+6f6876f59803009bffc7d75c4ed46f40b8f80426750d15bc1ddb14ac5dcb69a68242",
+ "ko": b"0611e1903609b47ad7a5fc2c82e47702",
+ },
+ {
+ "prf": "hmac_sha1",
+ "ctrlocation": "before_fixed",
+ "rlen": 8,
+ "l": 128,
+ "ki": b"a39bdf744ed7e33fdec060c8736e9725179885a8",
+ "fixedinputdatabytelen": b"60",
+ "fixedinputdata": b"af71b44940acff98949ad17f1ca20e8fdb3957cacdcd41e9\
+c591e18235019f90b9f8ee6e75700bcab2f8407525a104799b3e9725e27d738a9045e832",
+ "binary rep of i": b"01",
+ "instring": b"01af71b44940acff98949ad17f1ca20e8fdb3957cacdcd41e9c591\
+e18235019f90b9f8ee6e75700bcab2f8407525a104799b3e9725e27d738a9045e832",
+ "ko": b"51dc4668947e3685099bc3b5f8527468",
+ },
+ {
+ "prf": "hmac_sha224",
+ "ctrlocation": "after_fixed",
+ "rlen": 8,
+ "l": 128,
+ "ki": b"ab56556b107a3a79fe084df0f1bb3ad049a6cc1490f20da4b3df282c",
+ "fixedinputdatabytelen": b"60",
+ "fixedinputdata": b"7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43\
+aa1b91eeb5730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a7",
+ "binary rep of i": b"01",
+ "instring": b"7f50fc1f77c3ac752443154c1577d3c47b86fccffe82ff43aa1b91\
+eeb5730d7e9e6aab78374d854aecb7143faba6b1eb90d3d9e7a2f6d78dd9a6c4a701",
+ "ko": b"b8894c6133a46701909b5c8a84322dec",
+ },
]
def test_load_nist_ccm_vectors_dvpt():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.0
# "CCM-DVPT" information
# AES Keylen: 128
@@ -3606,61 +4260,63 @@ def test_load_nist_ccm_vectors_dvpt():
Adata = 00
CT = 3a65e03af37b81d05acc7ec1bc39deb0
Result = Fail
- """).splitlines()
+ """
+ ).splitlines()
assert load_nist_ccm_vectors(vector_data) == [
{
- 'key': b'4ae701103c63deca5b5a3939d7d05992',
- 'alen': 0,
- 'plen': 0,
- 'nlen': 7,
- 'tlen': 4,
- 'nonce': b'5a8aa485c316e9',
- 'adata': b'00',
- 'ct': b'02209f55',
- 'fail': False,
- 'payload': b'00'
- },
- {
- 'key': b'4ae701103c63deca5b5a3939d7d05992',
- 'alen': 0,
- 'plen': 0,
- 'nlen': 7,
- 'tlen': 4,
- 'nonce': b'3796cf51b87266',
- 'adata': b'00',
- 'ct': b'9a04c241',
- 'fail': True,
- 'payload': b'00'
- },
- {
- 'key': b'4bb3c4a4f893ad8c9bdc833c325d62b3',
- 'alen': 0,
- 'plen': 0,
- 'nlen': 7,
- 'tlen': 16,
- 'nonce': b'5a8aa485c316e9',
- 'adata': b'00',
- 'ct': b'75d582db43ce9b13ab4b6f7f14341330',
- 'fail': False,
- 'payload': b'00'
- },
- {
- 'key': b'4bb3c4a4f893ad8c9bdc833c325d62b3',
- 'alen': 0,
- 'plen': 0,
- 'nlen': 7,
- 'tlen': 16,
- 'nonce': b'3796cf51b87266',
- 'adata': b'00',
- 'ct': b'3a65e03af37b81d05acc7ec1bc39deb0',
- 'fail': True,
- 'payload': b'00'
- }
+ "key": b"4ae701103c63deca5b5a3939d7d05992",
+ "alen": 0,
+ "plen": 0,
+ "nlen": 7,
+ "tlen": 4,
+ "nonce": b"5a8aa485c316e9",
+ "adata": b"00",
+ "ct": b"02209f55",
+ "fail": False,
+ "payload": b"00",
+ },
+ {
+ "key": b"4ae701103c63deca5b5a3939d7d05992",
+ "alen": 0,
+ "plen": 0,
+ "nlen": 7,
+ "tlen": 4,
+ "nonce": b"3796cf51b87266",
+ "adata": b"00",
+ "ct": b"9a04c241",
+ "fail": True,
+ "payload": b"00",
+ },
+ {
+ "key": b"4bb3c4a4f893ad8c9bdc833c325d62b3",
+ "alen": 0,
+ "plen": 0,
+ "nlen": 7,
+ "tlen": 16,
+ "nonce": b"5a8aa485c316e9",
+ "adata": b"00",
+ "ct": b"75d582db43ce9b13ab4b6f7f14341330",
+ "fail": False,
+ "payload": b"00",
+ },
+ {
+ "key": b"4bb3c4a4f893ad8c9bdc833c325d62b3",
+ "alen": 0,
+ "plen": 0,
+ "nlen": 7,
+ "tlen": 16,
+ "nonce": b"3796cf51b87266",
+ "adata": b"00",
+ "ct": b"3a65e03af37b81d05acc7ec1bc39deb0",
+ "fail": True,
+ "payload": b"00",
+ },
]
def test_load_nist_ccm_vectors_vadt():
- vector_data = textwrap.dedent("""
+ vector_data = textwrap.dedent(
+ """
# CAVS 11.0
# "CCM-VADT" information
# AES Keylen: 128
@@ -3700,52 +4356,53 @@ def test_load_nist_ccm_vectors_vadt():
Adata = c5
Payload = 032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead
CT = f0828917020651c085e42459c544ec52e99372005362baf308ebe
- """).splitlines()
+ """
+ ).splitlines()
assert load_nist_ccm_vectors(vector_data) == [
{
- 'plen': 24,
- 'nlen': 13,
- 'tlen': 16,
- 'alen': 0,
- 'key': b'd24a3d3dde8c84830280cb87abad0bb3',
- 'nonce': b'f1100035bb24a8d26004e0e24b',
- 'adata': b'00',
- 'payload': b'7c86135ed9c2a515aaae0e9a208133897269220f30870006',
- 'ct': b'1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab11233'
- },
- {
- 'plen': 24,
- 'nlen': 13,
- 'tlen': 16,
- 'alen': 0,
- 'key': b'd24a3d3dde8c84830280cb87abad0bb3',
- 'nonce': b'f1100035bb24a8d26004e0e24b',
- 'adata': b'00',
- 'payload': b'48df73208cdc63d716752df7794807b1b2a80794a2433455',
- 'ct': b'642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d61'
- },
- {
- 'plen': 24,
- 'nlen': 13,
- 'tlen': 16,
- 'alen': 1,
- 'key': b'08b0da255d2083808a1b4d367090bacc',
- 'nonce': b'777828b13679a9e2ca89568233',
- 'adata': b'dd',
- 'payload': b'1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0',
- 'ct': b'e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6'
- },
- {
- 'plen': 24,
- 'nlen': 13,
- 'tlen': 16,
- 'alen': 1,
- 'key': b'08b0da255d2083808a1b4d367090bacc',
- 'nonce': b'777828b13679a9e2ca89568233',
- 'adata': b'c5',
- 'payload': b'032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead',
- 'ct': b'f0828917020651c085e42459c544ec52e99372005362baf308ebe'
- }
+ "plen": 24,
+ "nlen": 13,
+ "tlen": 16,
+ "alen": 0,
+ "key": b"d24a3d3dde8c84830280cb87abad0bb3",
+ "nonce": b"f1100035bb24a8d26004e0e24b",
+ "adata": b"00",
+ "payload": b"7c86135ed9c2a515aaae0e9a208133897269220f30870006",
+ "ct": b"1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab11233",
+ },
+ {
+ "plen": 24,
+ "nlen": 13,
+ "tlen": 16,
+ "alen": 0,
+ "key": b"d24a3d3dde8c84830280cb87abad0bb3",
+ "nonce": b"f1100035bb24a8d26004e0e24b",
+ "adata": b"00",
+ "payload": b"48df73208cdc63d716752df7794807b1b2a80794a2433455",
+ "ct": b"642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d61",
+ },
+ {
+ "plen": 24,
+ "nlen": 13,
+ "tlen": 16,
+ "alen": 1,
+ "key": b"08b0da255d2083808a1b4d367090bacc",
+ "nonce": b"777828b13679a9e2ca89568233",
+ "adata": b"dd",
+ "payload": b"1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0",
+ "ct": b"e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6",
+ },
+ {
+ "plen": 24,
+ "nlen": 13,
+ "tlen": 16,
+ "alen": 1,
+ "key": b"08b0da255d2083808a1b4d367090bacc",
+ "nonce": b"777828b13679a9e2ca89568233",
+ "adata": b"c5",
+ "payload": b"032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead",
+ "ct": b"f0828917020651c085e42459c544ec52e99372005362baf308ebe",
+ },
]
@@ -3767,16 +4424,15 @@ def test_raises_unsupported_algorithm_wrong_reason():
# Check that it fails if the wrong reason code is raised.
with pytest.raises(AssertionError):
with raises_unsupported_algorithm(None):
- raise UnsupportedAlgorithm("An error.",
- _Reasons.BACKEND_MISSING_INTERFACE)
+ raise UnsupportedAlgorithm(
+ "An error.", _Reasons.BACKEND_MISSING_INTERFACE
+ )
def test_raises_unsupported_no_exc():
# Check that it fails if no exception is raised.
with pytest.raises(pytest.fail.Exception):
- with raises_unsupported_algorithm(
- _Reasons.BACKEND_MISSING_INTERFACE
- ):
+ with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
pass
@@ -3785,6 +4441,7 @@ def test_raises_unsupported_algorithm():
with raises_unsupported_algorithm(
_Reasons.BACKEND_MISSING_INTERFACE
) as exc_info:
- raise UnsupportedAlgorithm("An error.",
- _Reasons.BACKEND_MISSING_INTERFACE)
+ raise UnsupportedAlgorithm(
+ "An error.", _Reasons.BACKEND_MISSING_INTERFACE
+ )
assert exc_info.type is UnsupportedAlgorithm
diff --git a/tests/test_warnings.py b/tests/test_warnings.py
index d27e757fc..073c699bc 100644
--- a/tests/test_warnings.py
+++ b/tests/test_warnings.py
@@ -21,7 +21,7 @@ class TestDeprecated(object):
value=1,
module_name=mod.__name__,
message="deprecated message text",
- warning_class=DeprecationWarning
+ warning_class=DeprecationWarning,
)
mod.Y = deprecated(
value=2,
@@ -55,7 +55,7 @@ class TestDeprecated(object):
value=1,
module_name=mod.__name__,
message="deprecated message text",
- warning_class=DeprecationWarning
+ warning_class=DeprecationWarning,
)
mod.Y = deprecated(
value=2,
diff --git a/tests/utils.py b/tests/utils.py
index b48128083..497fde83f 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -7,7 +7,6 @@ from __future__ import absolute_import, division, print_function
import binascii
import collections
import json
-import math
import os
import re
from contextlib import contextmanager
@@ -30,9 +29,7 @@ KeyedHashVector = collections.namedtuple(
def check_backend_support(backend, item):
for mark in item.node.iter_markers("supported"):
if not mark.kwargs["only_if"](backend):
- pytest.skip("{0} ({1})".format(
- mark.kwargs["skip_message"], backend
- ))
+ pytest.skip("{} ({})".format(mark.kwargs["skip_message"], backend))
@contextmanager
@@ -56,8 +53,11 @@ def load_nist_vectors(vector_data):
line = line.strip()
# Blank lines, comments, and section headers are ignored
- if not line or line.startswith("#") or (line.startswith("[") and
- line.endswith("]")):
+ if (
+ not line
+ or line.startswith("#")
+ or (line.startswith("[") and line.endswith("]"))
+ ):
continue
if line.strip() == "FAIL":
@@ -102,11 +102,9 @@ def load_cryptrec_vectors(vector_data):
ct = line.split(" : ")[1].replace(" ", "").encode("ascii")
# after a C is found the K+P+C tuple is complete
# there are many P+C pairs for each K
- cryptrec_list.append({
- "key": key,
- "plaintext": pt,
- "ciphertext": ct
- })
+ cryptrec_list.append(
+ {"key": key, "plaintext": pt, "ciphertext": ct}
+ )
else:
raise ValueError("Invalid line in file '{}'".format(line))
return cryptrec_list
@@ -164,9 +162,9 @@ def load_pkcs1_vectors(vector_data):
vectors = []
for line in vector_data:
if (
- line.startswith("# PSS Example") or
- line.startswith("# OAEP Example") or
- line.startswith("# PKCS#1 v1.5")
+ line.startswith("# PSS Example")
+ or line.startswith("# OAEP Example")
+ or line.startswith("# PKCS#1 v1.5")
):
if example_vector:
for key, value in six.iteritems(example_vector):
@@ -192,9 +190,8 @@ def load_pkcs1_vectors(vector_data):
elif line.startswith("# Encryption"):
attr = "encryption"
continue
- elif (
- example_vector and
- line.startswith("# =============================================")
+ elif example_vector and line.startswith(
+ "# ============================================="
):
for key, value in six.iteritems(example_vector):
hex_str = "".join(value).replace(" ", "").encode("ascii")
@@ -209,9 +206,8 @@ def load_pkcs1_vectors(vector_data):
example_vector[attr].append(line.strip())
continue
- if (
- line.startswith("# Example") or
- line.startswith("# =============================================")
+ if line.startswith("# Example") or line.startswith(
+ "# ============================================="
):
if key:
assert private_key_vector
@@ -229,18 +225,16 @@ def load_pkcs1_vectors(vector_data):
examples = []
assert (
- private_key_vector['public_exponent'] ==
- public_key_vector['public_exponent']
+ private_key_vector["public_exponent"]
+ == public_key_vector["public_exponent"]
)
assert (
- private_key_vector['modulus'] ==
- public_key_vector['modulus']
+ private_key_vector["modulus"]
+ == public_key_vector["modulus"]
)
- vectors.append(
- (private_key_vector, public_key_vector)
- )
+ vectors.append((private_key_vector, public_key_vector))
public_key_vector = collections.defaultdict(list)
private_key_vector = collections.defaultdict(list)
@@ -322,15 +316,10 @@ def load_rsa_nist_vectors(vector_data):
"public_exponent": e,
"salt_length": salt_length,
"algorithm": value,
- "fail": False
+ "fail": False,
}
else:
- test_data = {
- "modulus": n,
- "p": p,
- "q": q,
- "algorithm": value
- }
+ test_data = {"modulus": n, "p": p, "q": q, "algorithm": value}
if salt_length is not None:
test_data["salt_length"] = salt_length
data.append(test_data)
@@ -360,21 +349,24 @@ def load_fips_dsa_key_pair_vectors(vector_data):
continue
if line.startswith("P"):
- vectors.append({'p': int(line.split("=")[1], 16)})
+ vectors.append({"p": int(line.split("=")[1], 16)})
elif line.startswith("Q"):
- vectors[-1]['q'] = int(line.split("=")[1], 16)
+ vectors[-1]["q"] = int(line.split("=")[1], 16)
elif line.startswith("G"):
- vectors[-1]['g'] = int(line.split("=")[1], 16)
- elif line.startswith("X") and 'x' not in vectors[-1]:
- vectors[-1]['x'] = int(line.split("=")[1], 16)
- elif line.startswith("X") and 'x' in vectors[-1]:
- vectors.append({'p': vectors[-1]['p'],
- 'q': vectors[-1]['q'],
- 'g': vectors[-1]['g'],
- 'x': int(line.split("=")[1], 16)
- })
+ vectors[-1]["g"] = int(line.split("=")[1], 16)
+ elif line.startswith("X") and "x" not in vectors[-1]:
+ vectors[-1]["x"] = int(line.split("=")[1], 16)
+ elif line.startswith("X") and "x" in vectors[-1]:
+ vectors.append(
+ {
+ "p": vectors[-1]["p"],
+ "q": vectors[-1]["q"],
+ "g": vectors[-1]["g"],
+ "x": int(line.split("=")[1], 16),
+ }
+ )
elif line.startswith("Y"):
- vectors[-1]['y'] = int(line.split("=")[1], 16)
+ vectors[-1]["y"] = int(line.split("=")[1], 16)
return vectors
@@ -396,7 +388,7 @@ def load_fips_dsa_sig_vectors(vector_data):
sha_match = sha_regex.match(line)
if sha_match:
- digest_algorithm = "SHA-{0}".format(sha_match.group("sha"))
+ digest_algorithm = "SHA-{}".format(sha_match.group("sha"))
if line.startswith("[mod"):
continue
@@ -404,33 +396,37 @@ def load_fips_dsa_sig_vectors(vector_data):
name, value = [c.strip() for c in line.split("=")]
if name == "P":
- vectors.append({'p': int(value, 16),
- 'digest_algorithm': digest_algorithm})
+ vectors.append(
+ {"p": int(value, 16), "digest_algorithm": digest_algorithm}
+ )
elif name == "Q":
- vectors[-1]['q'] = int(value, 16)
+ vectors[-1]["q"] = int(value, 16)
elif name == "G":
- vectors[-1]['g'] = int(value, 16)
- elif name == "Msg" and 'msg' not in vectors[-1]:
+ vectors[-1]["g"] = int(value, 16)
+ elif name == "Msg" and "msg" not in vectors[-1]:
hexmsg = value.strip().encode("ascii")
- vectors[-1]['msg'] = binascii.unhexlify(hexmsg)
- elif name == "Msg" and 'msg' in vectors[-1]:
+ vectors[-1]["msg"] = binascii.unhexlify(hexmsg)
+ elif name == "Msg" and "msg" in vectors[-1]:
hexmsg = value.strip().encode("ascii")
- vectors.append({'p': vectors[-1]['p'],
- 'q': vectors[-1]['q'],
- 'g': vectors[-1]['g'],
- 'digest_algorithm':
- vectors[-1]['digest_algorithm'],
- 'msg': binascii.unhexlify(hexmsg)})
+ vectors.append(
+ {
+ "p": vectors[-1]["p"],
+ "q": vectors[-1]["q"],
+ "g": vectors[-1]["g"],
+ "digest_algorithm": vectors[-1]["digest_algorithm"],
+ "msg": binascii.unhexlify(hexmsg),
+ }
+ )
elif name == "X":
- vectors[-1]['x'] = int(value, 16)
+ vectors[-1]["x"] = int(value, 16)
elif name == "Y":
- vectors[-1]['y'] = int(value, 16)
+ vectors[-1]["y"] = int(value, 16)
elif name == "R":
- vectors[-1]['r'] = int(value, 16)
+ vectors[-1]["r"] = int(value, 16)
elif name == "S":
- vectors[-1]['s'] = int(value, 16)
+ vectors[-1]["s"] = int(value, 16)
elif name == "Result":
- vectors[-1]['result'] = value.split("(")[0].strip()
+ vectors[-1]["result"] = value.split("(")[0].strip()
return vectors
@@ -442,14 +438,12 @@ _ECDSA_CURVE_NAMES = {
"P-256": "secp256r1",
"P-384": "secp384r1",
"P-521": "secp521r1",
-
"K-163": "sect163k1",
"K-233": "sect233k1",
"K-256": "secp256k1",
"K-283": "sect283k1",
"K-409": "sect409k1",
"K-571": "sect571k1",
-
"B-163": "sect163r2",
"B-233": "sect233r1",
"B-283": "sect283r1",
@@ -477,10 +471,7 @@ def load_fips_ecdsa_key_pair_vectors(vector_data):
if key_data is not None:
vectors.append(key_data)
- key_data = {
- "curve": curve_name,
- "d": int(line.split("=")[1], 16)
- }
+ key_data = {"curve": curve_name, "d": int(line.split("=")[1], 16)}
elif key_data is not None:
if line.startswith("Qx = "):
@@ -511,7 +502,7 @@ def load_fips_ecdsa_signing_vectors(vector_data):
curve_match = curve_rx.match(line)
if curve_match:
curve_name = _ECDSA_CURVE_NAMES[curve_match.group("curve")]
- digest_name = "SHA-{0}".format(curve_match.group("sha"))
+ digest_name = "SHA-{}".format(curve_match.group("sha"))
elif line.startswith("Msg = "):
if data is not None:
@@ -522,7 +513,7 @@ def load_fips_ecdsa_signing_vectors(vector_data):
data = {
"curve": curve_name,
"digest_algorithm": digest_name,
- "message": binascii.unhexlify(hexmsg)
+ "message": binascii.unhexlify(hexmsg),
}
elif data is not None:
@@ -552,10 +543,7 @@ def load_kasvs_dh_vectors(vector_data):
result_rx = re.compile(r"([FP]) \(([0-9]+) -")
vectors = []
- data = {
- "fail_z": False,
- "fail_agree": False
- }
+ data = {"fail_z": False, "fail_agree": False}
for line in vector_data:
line = line.strip()
@@ -597,7 +585,7 @@ def load_kasvs_dh_vectors(vector_data):
"q": data["q"],
"g": data["g"],
"fail_z": False,
- "fail_agree": False
+ "fail_agree": False,
}
return vectors
@@ -647,7 +635,7 @@ def load_kasvs_ecdh_vectors(vector_data):
tag = line
curve = None
elif line.startswith("[Curve selected:"):
- curve = curve_name_map[line.split(':')[1].strip()[:-1]]
+ curve = curve_name_map[line.split(":")[1].strip()[:-1]]
if tag is not None and curve is not None:
sets[tag.strip("[]")] = curve
@@ -744,15 +732,15 @@ def load_x963_vectors(vector_data):
vector["key_data_length"] = key_data_len
elif line.startswith("Z"):
vector["Z"] = line.split("=")[1].strip()
- assert math.ceil(shared_secret_len / 8) * 2 == len(vector["Z"])
+ assert ((shared_secret_len + 7) // 8) * 2 == len(vector["Z"])
elif line.startswith("SharedInfo"):
if shared_info_len != 0:
vector["sharedinfo"] = line.split("=")[1].strip()
silen = len(vector["sharedinfo"])
- assert math.ceil(shared_info_len / 8) * 2 == silen
+ assert ((shared_info_len + 7) // 8) * 2 == silen
elif line.startswith("key_data"):
vector["key_data"] = line.split("=")[1].strip()
- assert math.ceil(key_data_len / 8) * 2 == len(vector["key_data"])
+ assert ((key_data_len + 7) // 8) * 2 == len(vector["key_data"])
vectors.append(vector)
vector = {}
@@ -776,14 +764,14 @@ def load_nist_kbkdf_vectors(vector_data):
if line.startswith("[") and line.endswith("]"):
tag_data = line[1:-1]
name, value = [c.strip() for c in tag_data.split("=")]
- if value.endswith('_BITS'):
- value = int(value.split('_')[0])
+ if value.endswith("_BITS"):
+ value = int(value.split("_")[0])
tag.update({name.lower(): value})
continue
tag.update({name.lower(): value.lower()})
elif line.startswith("COUNT="):
- test_data = dict()
+ test_data = {}
test_data.update(tag)
vectors.append(test_data)
elif line.startswith("L"):
@@ -799,17 +787,19 @@ def load_nist_kbkdf_vectors(vector_data):
def load_ed25519_vectors(vector_data):
data = []
for line in vector_data:
- secret_key, public_key, message, signature, _ = line.split(':')
+ secret_key, public_key, message, signature, _ = line.split(":")
# In the vectors the first element is secret key + public key
secret_key = secret_key[0:64]
# In the vectors the signature section is signature + message
signature = signature[0:128]
- data.append({
- "secret_key": secret_key,
- "public_key": public_key,
- "message": message,
- "signature": signature
- })
+ data.append(
+ {
+ "secret_key": secret_key,
+ "public_key": public_key,
+ "message": message,
+ "signature": signature,
+ }
+ )
return data
@@ -887,13 +877,17 @@ def load_nist_ccm_vectors(vector_data):
class WycheproofTest(object):
- def __init__(self, testgroup, testcase):
+ def __init__(self, testfiledata, testgroup, testcase):
+ self.testfiledata = testfiledata
self.testgroup = testgroup
self.testcase = testcase
def __repr__(self):
- return "<WycheproofTest({!r}, {!r}, tcId={})>".format(
- self.testgroup, self.testcase, self.testcase["tcId"],
+ return "<WycheproofTest({!r}, {!r}, {!r}, tcId={})>".format(
+ self.testfiledata,
+ self.testgroup,
+ self.testcase,
+ self.testcase["tcId"],
)
@property
@@ -912,18 +906,11 @@ class WycheproofTest(object):
return flag in self.testcase["flags"]
-def skip_if_wycheproof_none(wycheproof):
- # This is factored into its own function so we can easily test both
- # branches
- if wycheproof is None:
- pytest.skip("--wycheproof-root not provided")
-
-
def load_wycheproof_tests(wycheproof, test_file):
path = os.path.join(wycheproof, "testvectors", test_file)
with open(path) as f:
data = json.load(f)
- for group in data["testGroups"]:
+ for group in data.pop("testGroups"):
cases = group.pop("tests")
for c in cases:
- yield WycheproofTest(group, c)
+ yield WycheproofTest(data, group, c)
diff --git a/tests/wycheproof/test_aes.py b/tests/wycheproof/test_aes.py
index 55e454546..9992095ae 100644
--- a/tests/wycheproof/test_aes.py
+++ b/tests/wycheproof/test_aes.py
@@ -11,9 +11,7 @@ import pytest
from cryptography.exceptions import InvalidTag
from cryptography.hazmat.backends.interfaces import CipherBackend
from cryptography.hazmat.primitives import padding
-from cryptography.hazmat.primitives.ciphers import (
- Cipher, algorithms, modes
-)
+from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.ciphers.aead import AESCCM, AESGCM
from ..hazmat.primitives.test_aead import _aead_supported
@@ -31,8 +29,9 @@ def test_aes_cbc_pkcs5(backend, wycheproof):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend)
enc = cipher.encryptor()
- computed_ct = enc.update(
- padder.update(msg) + padder.finalize()) + enc.finalize()
+ computed_ct = (
+ enc.update(padder.update(msg) + padder.finalize()) + enc.finalize()
+ )
dec = cipher.decryptor()
padded_msg = dec.update(ct) + dec.finalize()
unpadder = padding.PKCS7(128).unpadder()
@@ -55,6 +54,15 @@ def test_aes_gcm(backend, wycheproof):
msg = binascii.unhexlify(wycheproof.testcase["msg"])
ct = binascii.unhexlify(wycheproof.testcase["ct"])
tag = binascii.unhexlify(wycheproof.testcase["tag"])
+ if len(iv) < 8 or len(iv) > 128:
+ pytest.skip(
+ "Less than 64-bit IVs (and greater than 1024-bit) are no longer "
+ "supported"
+ )
+ if backend._fips_enabled and len(iv) != 12:
+ # Red Hat disables non-96-bit IV support as part of its FIPS
+ # patches.
+ pytest.skip("Non-96-bit IVs unsupported in FIPS mode.")
if wycheproof.valid or wycheproof.acceptable:
enc = Cipher(algorithms.AES(key), modes.GCM(iv), backend).encryptor()
enc.authenticate_additional_data(aad)
@@ -65,19 +73,16 @@ def test_aes_gcm(backend, wycheproof):
dec = Cipher(
algorithms.AES(key),
modes.GCM(iv, tag, min_tag_length=len(tag)),
- backend
+ backend,
).decryptor()
dec.authenticate_additional_data(aad)
computed_msg = dec.update(ct) + dec.finalize()
assert computed_msg == msg
- elif len(iv) == 0:
- with pytest.raises(ValueError):
- Cipher(algorithms.AES(key), modes.GCM(iv), backend)
else:
dec = Cipher(
algorithms.AES(key),
modes.GCM(iv, tag, min_tag_length=len(tag)),
- backend
+ backend,
).decryptor()
dec.authenticate_additional_data(aad)
dec.update(ct)
@@ -94,15 +99,22 @@ def test_aes_gcm_aead_api(backend, wycheproof):
msg = binascii.unhexlify(wycheproof.testcase["msg"])
ct = binascii.unhexlify(wycheproof.testcase["ct"])
tag = binascii.unhexlify(wycheproof.testcase["tag"])
+ if len(iv) < 8 or len(iv) > 128:
+ pytest.skip(
+ "Less than 64-bit IVs (and greater than 1024-bit) are no longer "
+ "supported"
+ )
+
+ if backend._fips_enabled and len(iv) != 12:
+ # Red Hat disables non-96-bit IV support as part of its FIPS
+ # patches.
+ pytest.skip("Non-96-bit IVs unsupported in FIPS mode.")
aesgcm = AESGCM(key)
if wycheproof.valid or wycheproof.acceptable:
computed_ct = aesgcm.encrypt(iv, msg, aad)
assert computed_ct == ct + tag
computed_msg = aesgcm.decrypt(iv, ct + tag, aad)
assert computed_msg == msg
- elif len(iv) == 0:
- with pytest.raises(ValueError):
- aesgcm.encrypt(iv, msg, aad)
else:
with pytest.raises(InvalidTag):
aesgcm.decrypt(iv, ct + tag, aad)
@@ -123,8 +135,8 @@ def test_aes_ccm_aead_api(backend, wycheproof):
tag = binascii.unhexlify(wycheproof.testcase["tag"])
if (
- wycheproof.invalid and
- wycheproof.testcase["comment"] == "Invalid tag size"
+ wycheproof.invalid
+ and wycheproof.testcase["comment"] == "Invalid tag size"
):
with pytest.raises(ValueError):
AESCCM(key, tag_length=wycheproof.testgroup["tagSize"] // 8)
diff --git a/tests/wycheproof/test_chacha20poly1305.py b/tests/wycheproof/test_chacha20poly1305.py
index deef5a0a7..48023ca63 100644
--- a/tests/wycheproof/test_chacha20poly1305.py
+++ b/tests/wycheproof/test_chacha20poly1305.py
@@ -17,7 +17,7 @@ from ..hazmat.primitives.test_aead import _aead_supported
@pytest.mark.skipif(
not _aead_supported(ChaCha20Poly1305),
- reason="Requires OpenSSL with ChaCha20Poly1305 support"
+ reason="Requires OpenSSL with ChaCha20Poly1305 support",
)
@pytest.mark.requires_backend_interface(interface=CipherBackend)
@pytest.mark.wycheproof_tests("chacha20_poly1305_test.json")
diff --git a/tests/wycheproof/test_dsa.py b/tests/wycheproof/test_dsa.py
index 3dc3056e1..9185b3e2f 100644
--- a/tests/wycheproof/test_dsa.py
+++ b/tests/wycheproof/test_dsa.py
@@ -23,6 +23,10 @@ _DIGESTS = {
@pytest.mark.requires_backend_interface(interface=DSABackend)
@pytest.mark.wycheproof_tests(
"dsa_test.json",
+ "dsa_2048_224_sha224_test.json",
+ "dsa_2048_224_sha256_test.json",
+ "dsa_2048_256_sha256_test.json",
+ "dsa_3072_256_sha256_test.json",
)
def test_dsa_signature(backend, wycheproof):
key = serialization.load_der_public_key(
@@ -30,10 +34,8 @@ def test_dsa_signature(backend, wycheproof):
)
digest = _DIGESTS[wycheproof.testgroup["sha"]]
- if (
- wycheproof.valid or (
- wycheproof.acceptable and not wycheproof.has_flag("NoLeadingZero")
- )
+ if wycheproof.valid or (
+ wycheproof.acceptable and not wycheproof.has_flag("NoLeadingZero")
):
key.verify(
binascii.unhexlify(wycheproof.testcase["sig"]),
diff --git a/tests/wycheproof/test_ecdh.py b/tests/wycheproof/test_ecdh.py
index 5fcc45b76..b89dc68ce 100644
--- a/tests/wycheproof/test_ecdh.py
+++ b/tests/wycheproof/test_ecdh.py
@@ -21,6 +21,7 @@ _CURVES = {
"secp256r1": ec.SECP256R1(),
"secp384r1": ec.SECP384R1(),
"secp521r1": ec.SECP521R1(),
+ "secp224k1": None,
"secp256k1": ec.SECP256K1(),
"brainpoolP224r1": None,
"brainpoolP256r1": ec.BrainpoolP256R1(),
diff --git a/tests/wycheproof/test_ecdsa.py b/tests/wycheproof/test_ecdsa.py
index 5214052ec..802bb9f00 100644
--- a/tests/wycheproof/test_ecdsa.py
+++ b/tests/wycheproof/test_ecdsa.py
@@ -20,6 +20,10 @@ _DIGESTS = {
"SHA-256": hashes.SHA256(),
"SHA-384": hashes.SHA384(),
"SHA-512": hashes.SHA512(),
+ "SHA3-224": hashes.SHA3_224(),
+ "SHA3-256": hashes.SHA3_256(),
+ "SHA3-384": hashes.SHA3_384(),
+ "SHA3-512": hashes.SHA3_512(),
}
@@ -34,13 +38,23 @@ _DIGESTS = {
"ecdsa_secp224r1_sha224_test.json",
"ecdsa_secp224r1_sha256_test.json",
"ecdsa_secp224r1_sha512_test.json",
+ "ecdsa_secp224r1_sha3_224_test.json",
+ "ecdsa_secp224r1_sha3_256_test.json",
+ "ecdsa_secp224r1_sha3_512_test.json",
"ecdsa_secp256k1_sha256_test.json",
"ecdsa_secp256k1_sha512_test.json",
+ "ecdsa_secp256k1_sha3_256_test.json",
+ "ecdsa_secp256k1_sha3_512_test.json",
"ecdsa_secp256r1_sha256_test.json",
"ecdsa_secp256r1_sha512_test.json",
+ "ecdsa_secp256r1_sha3_256_test.json",
+ "ecdsa_secp256r1_sha3_512_test.json",
"ecdsa_secp384r1_sha384_test.json",
"ecdsa_secp384r1_sha512_test.json",
+ "ecdsa_secp384r1_sha3_384_test.json",
+ "ecdsa_secp384r1_sha3_512_test.json",
"ecdsa_secp521r1_sha512_test.json",
+ "ecdsa_secp521r1_sha3_512_test.json",
)
def test_ecdsa_signature(backend, wycheproof):
try:
@@ -48,9 +62,9 @@ def test_ecdsa_signature(backend, wycheproof):
binascii.unhexlify(wycheproof.testgroup["keyDer"]), backend
)
except (UnsupportedAlgorithm, ValueError):
- # In OpenSSL 1.0.1, some keys fail to load with ValueError, instead of
- # Unsupported Algorithm. We can remove handling for that exception
- # when we drop support.
+ # In some OpenSSL 1.0.2s, some keys fail to load with ValueError,
+ # instead of Unsupported Algorithm. We can remove handling for that
+ # exception when we drop support.
pytest.skip(
"unable to load key (curve {})".format(
wycheproof.testgroup["key"]["curve"]
@@ -58,9 +72,11 @@ def test_ecdsa_signature(backend, wycheproof):
)
digest = _DIGESTS[wycheproof.testgroup["sha"]]
- if (
- wycheproof.valid or
- (wycheproof.acceptable and not wycheproof.has_flag("MissingZero"))
+ if not backend.hash_supported(digest):
+ pytest.skip("Hash {} not supported".format(digest))
+
+ if wycheproof.valid or (
+ wycheproof.acceptable and not wycheproof.has_flag("MissingZero")
):
key.verify(
binascii.unhexlify(wycheproof.testcase["sig"]),
diff --git a/tests/wycheproof/test_eddsa.py b/tests/wycheproof/test_eddsa.py
new file mode 100644
index 000000000..42c1498af
--- /dev/null
+++ b/tests/wycheproof/test_eddsa.py
@@ -0,0 +1,63 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+import pytest
+
+from cryptography.exceptions import InvalidSignature
+from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
+from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PublicKey
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+)
+@pytest.mark.wycheproof_tests("eddsa_test.json")
+def test_ed25519_signature(backend, wycheproof):
+ # We want to fail if/when wycheproof adds more edwards curve tests
+ # so we can add them as well.
+ assert wycheproof.testgroup["key"]["curve"] == "edwards25519"
+
+ key = Ed25519PublicKey.from_public_bytes(
+ binascii.unhexlify(wycheproof.testgroup["key"]["pk"])
+ )
+
+ if wycheproof.valid or wycheproof.acceptable:
+ key.verify(
+ binascii.unhexlify(wycheproof.testcase["sig"]),
+ binascii.unhexlify(wycheproof.testcase["msg"]),
+ )
+ else:
+ with pytest.raises(InvalidSignature):
+ key.verify(
+ binascii.unhexlify(wycheproof.testcase["sig"]),
+ binascii.unhexlify(wycheproof.testcase["msg"]),
+ )
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+)
+@pytest.mark.wycheproof_tests("ed448_test.json")
+def test_ed448_signature(backend, wycheproof):
+ key = Ed448PublicKey.from_public_bytes(
+ binascii.unhexlify(wycheproof.testgroup["key"]["pk"])
+ )
+
+ if wycheproof.valid or wycheproof.acceptable:
+ key.verify(
+ binascii.unhexlify(wycheproof.testcase["sig"]),
+ binascii.unhexlify(wycheproof.testcase["msg"]),
+ )
+ else:
+ with pytest.raises(InvalidSignature):
+ key.verify(
+ binascii.unhexlify(wycheproof.testcase["sig"]),
+ binascii.unhexlify(wycheproof.testcase["msg"]),
+ )
diff --git a/tests/wycheproof/test_hkdf.py b/tests/wycheproof/test_hkdf.py
new file mode 100644
index 000000000..3e1687ea3
--- /dev/null
+++ b/tests/wycheproof/test_hkdf.py
@@ -0,0 +1,50 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+import pytest
+
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+
+
+_HASH_ALGORITHMS = {
+ "HKDF-SHA-1": hashes.SHA1(),
+ "HKDF-SHA-256": hashes.SHA256(),
+ "HKDF-SHA-384": hashes.SHA384(),
+ "HKDF-SHA-512": hashes.SHA512(),
+}
+
+
+@pytest.mark.wycheproof_tests(
+ "hkdf_sha1_test.json",
+ "hkdf_sha256_test.json",
+ "hkdf_sha384_test.json",
+ "hkdf_sha512_test.json",
+)
+def test_hkdf(backend, wycheproof):
+ hash_algo = _HASH_ALGORITHMS[wycheproof.testfiledata["algorithm"]]
+ if wycheproof.invalid:
+ with pytest.raises(ValueError):
+ HKDF(
+ algorithm=hash_algo,
+ length=wycheproof.testcase["size"],
+ salt=binascii.unhexlify(wycheproof.testcase["salt"]),
+ info=binascii.unhexlify(wycheproof.testcase["info"]),
+ backend=backend,
+ )
+ return
+
+ h = HKDF(
+ algorithm=hash_algo,
+ length=wycheproof.testcase["size"],
+ salt=binascii.unhexlify(wycheproof.testcase["salt"]),
+ info=binascii.unhexlify(wycheproof.testcase["info"]),
+ backend=backend,
+ )
+ result = h.derive(binascii.unhexlify(wycheproof.testcase["ikm"]))
+ assert result == binascii.unhexlify(wycheproof.testcase["okm"])
diff --git a/tests/wycheproof/test_hmac.py b/tests/wycheproof/test_hmac.py
new file mode 100644
index 000000000..0cf908fe9
--- /dev/null
+++ b/tests/wycheproof/test_hmac.py
@@ -0,0 +1,66 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+import pytest
+
+from cryptography.exceptions import InvalidSignature
+from cryptography.hazmat.primitives import hashes, hmac
+
+
+_HMAC_ALGORITHMS = {
+ "HMACSHA1": hashes.SHA1(),
+ "HMACSHA224": hashes.SHA224(),
+ "HMACSHA256": hashes.SHA256(),
+ "HMACSHA384": hashes.SHA384(),
+ "HMACSHA512": hashes.SHA512(),
+ "HMACSHA3-224": hashes.SHA3_224(),
+ "HMACSHA3-256": hashes.SHA3_256(),
+ "HMACSHA3-384": hashes.SHA3_384(),
+ "HMACSHA3-512": hashes.SHA3_512(),
+}
+
+
+@pytest.mark.wycheproof_tests(
+ "hmac_sha1_test.json",
+ "hmac_sha224_test.json",
+ "hmac_sha256_test.json",
+ "hmac_sha384_test.json",
+ "hmac_sha3_224_test.json",
+ "hmac_sha3_256_test.json",
+ "hmac_sha3_384_test.json",
+ "hmac_sha3_512_test.json",
+ "hmac_sha512_test.json",
+)
+def test_hmac(backend, wycheproof):
+ hash_algo = _HMAC_ALGORITHMS[wycheproof.testfiledata["algorithm"]]
+ if wycheproof.testgroup["tagSize"] // 8 != hash_algo.digest_size:
+ pytest.skip("Truncated HMAC not supported")
+ if not backend.hash_supported(hash_algo):
+ pytest.skip("Hash {} not supported".format(hash_algo.name))
+
+ h = hmac.HMAC(
+ key=binascii.unhexlify(wycheproof.testcase["key"]),
+ algorithm=hash_algo,
+ backend=backend,
+ )
+ h.update(binascii.unhexlify(wycheproof.testcase["msg"]))
+
+ if wycheproof.invalid:
+ with pytest.raises(InvalidSignature):
+ h.verify(binascii.unhexlify(wycheproof.testcase["tag"]))
+ else:
+ tag = h.finalize()
+ assert tag == binascii.unhexlify(wycheproof.testcase["tag"])
+
+ h = hmac.HMAC(
+ key=binascii.unhexlify(wycheproof.testcase["key"]),
+ algorithm=hash_algo,
+ backend=backend,
+ )
+ h.update(binascii.unhexlify(wycheproof.testcase["msg"]))
+ h.verify(binascii.unhexlify(wycheproof.testcase["tag"]))
diff --git a/tests/wycheproof/test_keywrap.py b/tests/wycheproof/test_keywrap.py
index 5f694e4d3..9c7d522e6 100644
--- a/tests/wycheproof/test_keywrap.py
+++ b/tests/wycheproof/test_keywrap.py
@@ -44,11 +44,9 @@ def test_keywrap(backend, wycheproof):
key_to_wrap = binascii.unhexlify(wycheproof.testcase["msg"])
expected = binascii.unhexlify(wycheproof.testcase["ct"])
- if (
- wycheproof.valid or (
- wycheproof.acceptable and
- wycheproof.testcase["comment"] != "invalid size of wrapped key"
- )
+ if wycheproof.valid or (
+ wycheproof.acceptable
+ and wycheproof.testcase["comment"] != "invalid size of wrapped key"
):
result = keywrap.aes_key_wrap(wrapping_key, key_to_wrap, backend)
assert result == expected
diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py
index 3d35f42d7..926bb44e9 100644
--- a/tests/wycheproof/test_rsa.py
+++ b/tests/wycheproof/test_rsa.py
@@ -20,6 +20,13 @@ _DIGESTS = {
"SHA-256": hashes.SHA256(),
"SHA-384": hashes.SHA384(),
"SHA-512": hashes.SHA512(),
+ # Not supported by OpenSSL for RSA signing
+ "SHA-512/224": None,
+ "SHA-512/256": None,
+ "SHA3-224": hashes.SHA3_224(),
+ "SHA3-256": hashes.SHA3_256(),
+ "SHA3-384": hashes.SHA3_384(),
+ "SHA3-512": hashes.SHA3_512(),
}
@@ -28,39 +35,34 @@ def should_verify(backend, wycheproof):
return True
if wycheproof.acceptable:
- if (
- backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER and
- wycheproof.has_flag("MissingNull")
- ):
- return False
- return True
+ return not wycheproof.has_flag("MissingNull")
return False
@pytest.mark.requires_backend_interface(interface=RSABackend)
-@pytest.mark.supported(
- only_if=lambda backend: (
- # TODO: this also skips on LibreSSL, which is ok for now, since these
- # don't pass on Libre, but we'll need to fix this when LibreSSL 2.8 is
- # released.
- not backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102
- ),
- skip_message=(
- "Many of these tests fail on OpenSSL < 1.0.2 and since upstream isn't"
- " maintaining it, they'll never be fixed."
- ),
-)
@pytest.mark.wycheproof_tests(
"rsa_signature_test.json",
"rsa_signature_2048_sha224_test.json",
"rsa_signature_2048_sha256_test.json",
+ "rsa_signature_2048_sha384_test.json",
"rsa_signature_2048_sha512_test.json",
+ "rsa_signature_2048_sha512_224_test.json",
+ "rsa_signature_2048_sha512_256_test.json",
+ "rsa_signature_2048_sha3_224_test.json",
+ "rsa_signature_2048_sha3_256_test.json",
+ "rsa_signature_2048_sha3_384_test.json",
+ "rsa_signature_2048_sha3_512_test.json",
"rsa_signature_3072_sha256_test.json",
"rsa_signature_3072_sha384_test.json",
"rsa_signature_3072_sha512_test.json",
+ "rsa_signature_3072_sha512_256_test.json",
+ "rsa_signature_3072_sha3_256_test.json",
+ "rsa_signature_3072_sha3_384_test.json",
+ "rsa_signature_3072_sha3_512_test.json",
"rsa_signature_4096_sha384_test.json",
"rsa_signature_4096_sha512_test.json",
+ "rsa_signature_4096_sha512_256_test.json",
)
def test_rsa_pkcs1v15_signature(backend, wycheproof):
key = serialization.load_der_public_key(
@@ -68,6 +70,11 @@ def test_rsa_pkcs1v15_signature(backend, wycheproof):
)
digest = _DIGESTS[wycheproof.testgroup["sha"]]
+ if digest is None or not backend.hash_supported(digest):
+ pytest.skip(
+ "Hash {} not supported".format(wycheproof.testgroup["sha"])
+ )
+
if should_verify(backend, wycheproof):
key.verify(
binascii.unhexlify(wycheproof.testcase["sig"]),
@@ -85,11 +92,30 @@ def test_rsa_pkcs1v15_signature(backend, wycheproof):
)
+@pytest.mark.wycheproof_tests("rsa_sig_gen_misc_test.json")
+def test_rsa_pkcs1v15_signature_generation(backend, wycheproof):
+ key = serialization.load_pem_private_key(
+ wycheproof.testgroup["privateKeyPem"].encode(),
+ password=None,
+ backend=backend,
+ )
+ digest = _DIGESTS[wycheproof.testgroup["sha"]]
+
+ sig = key.sign(
+ binascii.unhexlify(wycheproof.testcase["msg"]),
+ padding.PKCS1v15(),
+ digest,
+ )
+ assert sig == binascii.unhexlify(wycheproof.testcase["sig"])
+
+
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.wycheproof_tests(
"rsa_pss_2048_sha1_mgf1_20_test.json",
"rsa_pss_2048_sha256_mgf1_0_test.json",
"rsa_pss_2048_sha256_mgf1_32_test.json",
+ "rsa_pss_2048_sha512_256_mgf1_28_test.json",
+ "rsa_pss_2048_sha512_256_mgf1_32_test.json",
"rsa_pss_3072_sha256_mgf1_32_test.json",
"rsa_pss_4096_sha256_mgf1_32_test.json",
"rsa_pss_4096_sha512_mgf1_32_test.json",
@@ -102,15 +128,23 @@ def test_rsa_pss_signature(backend, wycheproof):
digest = _DIGESTS[wycheproof.testgroup["sha"]]
mgf_digest = _DIGESTS[wycheproof.testgroup["mgfSha"]]
+ if digest is None or mgf_digest is None:
+ pytest.skip(
+ "PSS with digest={} and MGF digest={} not supported".format(
+ wycheproof.testgroup["sha"],
+ wycheproof.testgroup["mgfSha"],
+ )
+ )
+
if wycheproof.valid or wycheproof.acceptable:
key.verify(
binascii.unhexlify(wycheproof.testcase["sig"]),
binascii.unhexlify(wycheproof.testcase["msg"]),
padding.PSS(
mgf=padding.MGF1(mgf_digest),
- salt_length=wycheproof.testgroup["sLen"]
+ salt_length=wycheproof.testgroup["sLen"],
),
- digest
+ digest,
)
else:
with pytest.raises(InvalidSignature):
@@ -119,7 +153,88 @@ def test_rsa_pss_signature(backend, wycheproof):
binascii.unhexlify(wycheproof.testcase["msg"]),
padding.PSS(
mgf=padding.MGF1(mgf_digest),
- salt_length=wycheproof.testgroup["sLen"]
+ salt_length=wycheproof.testgroup["sLen"],
),
- digest
+ digest,
+ )
+
+
+@pytest.mark.requires_backend_interface(interface=RSABackend)
+@pytest.mark.wycheproof_tests(
+ "rsa_oaep_2048_sha1_mgf1sha1_test.json",
+ "rsa_oaep_2048_sha224_mgf1sha1_test.json",
+ "rsa_oaep_2048_sha224_mgf1sha224_test.json",
+ "rsa_oaep_2048_sha256_mgf1sha1_test.json",
+ "rsa_oaep_2048_sha256_mgf1sha256_test.json",
+ "rsa_oaep_2048_sha384_mgf1sha1_test.json",
+ "rsa_oaep_2048_sha384_mgf1sha384_test.json",
+ "rsa_oaep_2048_sha512_mgf1sha1_test.json",
+ "rsa_oaep_2048_sha512_mgf1sha512_test.json",
+ "rsa_oaep_3072_sha256_mgf1sha1_test.json",
+ "rsa_oaep_3072_sha256_mgf1sha256_test.json",
+ "rsa_oaep_3072_sha512_mgf1sha1_test.json",
+ "rsa_oaep_3072_sha512_mgf1sha512_test.json",
+ "rsa_oaep_4096_sha256_mgf1sha1_test.json",
+ "rsa_oaep_4096_sha256_mgf1sha256_test.json",
+ "rsa_oaep_4096_sha512_mgf1sha1_test.json",
+ "rsa_oaep_4096_sha512_mgf1sha512_test.json",
+ "rsa_oaep_misc_test.json",
+)
+def test_rsa_oaep_encryption(backend, wycheproof):
+ key = serialization.load_pem_private_key(
+ wycheproof.testgroup["privateKeyPem"].encode("ascii"),
+ password=None,
+ backend=backend,
+ )
+ digest = _DIGESTS[wycheproof.testgroup["sha"]]
+ mgf_digest = _DIGESTS[wycheproof.testgroup["mgfSha"]]
+
+ padding_algo = padding.OAEP(
+ mgf=padding.MGF1(algorithm=mgf_digest),
+ algorithm=digest,
+ label=binascii.unhexlify(wycheproof.testcase["label"]),
+ )
+
+ if not backend.rsa_padding_supported(padding_algo):
+ pytest.skip(
+ "OAEP with digest={} and MGF digest={} not supported".format(
+ wycheproof.testgroup["sha"],
+ wycheproof.testgroup["mgfSha"],
+ )
+ )
+
+ if wycheproof.valid or wycheproof.acceptable:
+ pt = key.decrypt(
+ binascii.unhexlify(wycheproof.testcase["ct"]), padding_algo
+ )
+ assert pt == binascii.unhexlify(wycheproof.testcase["msg"])
+ else:
+ with pytest.raises(ValueError):
+ key.decrypt(
+ binascii.unhexlify(wycheproof.testcase["ct"]), padding_algo
+ )
+
+
+@pytest.mark.wycheproof_tests(
+ "rsa_pkcs1_2048_test.json",
+ "rsa_pkcs1_3072_test.json",
+ "rsa_pkcs1_4096_test.json",
+)
+def test_rsa_pkcs1_encryption(backend, wycheproof):
+ key = serialization.load_pem_private_key(
+ wycheproof.testgroup["privateKeyPem"].encode("ascii"),
+ password=None,
+ backend=backend,
+ )
+
+ if wycheproof.valid:
+ pt = key.decrypt(
+ binascii.unhexlify(wycheproof.testcase["ct"]), padding.PKCS1v15()
+ )
+ assert pt == binascii.unhexlify(wycheproof.testcase["msg"])
+ else:
+ with pytest.raises(ValueError):
+ key.decrypt(
+ binascii.unhexlify(wycheproof.testcase["ct"]),
+ padding.PKCS1v15(),
)
diff --git a/tests/wycheproof/test_utils.py b/tests/wycheproof/test_utils.py
index 82c0a3596..593d26bde 100644
--- a/tests/wycheproof/test_utils.py
+++ b/tests/wycheproof/test_utils.py
@@ -4,18 +4,9 @@
from __future__ import absolute_import, division, print_function
-import pytest
-
-from ..utils import WycheproofTest, skip_if_wycheproof_none
+from ..utils import WycheproofTest
def test_wycheproof_test_repr():
- wycheproof = WycheproofTest({}, {"tcId": 3})
- assert repr(wycheproof) == "<WycheproofTest({}, {'tcId': 3}, tcId=3)>"
-
-
-def test_skip_if_wycheproof_none():
- with pytest.raises(pytest.skip.Exception):
- skip_if_wycheproof_none(None)
-
- skip_if_wycheproof_none("abc")
+ wycheproof = WycheproofTest({}, {}, {"tcId": 3})
+ assert repr(wycheproof) == "<WycheproofTest({}, {}, {'tcId': 3}, tcId=3)>"
diff --git a/tests/wycheproof/test_x25519.py b/tests/wycheproof/test_x25519.py
index 0727ec39d..ce2a965e3 100644
--- a/tests/wycheproof/test_x25519.py
+++ b/tests/wycheproof/test_x25519.py
@@ -8,20 +8,22 @@ import binascii
import pytest
-from cryptography.hazmat.backends.interfaces import DHBackend
from cryptography.hazmat.primitives.asymmetric.x25519 import (
- X25519PrivateKey, X25519PublicKey
+ X25519PrivateKey,
+ X25519PublicKey,
)
@pytest.mark.supported(
only_if=lambda backend: backend.x25519_supported(),
- skip_message="Requires OpenSSL with X25519 support"
+ skip_message="Requires OpenSSL with X25519 support",
)
-@pytest.mark.requires_backend_interface(interface=DHBackend)
@pytest.mark.wycheproof_tests("x25519_test.json")
def test_x25519(backend, wycheproof):
- assert list(wycheproof.testgroup.items()) == [("curve", "curve25519")]
+ assert set(wycheproof.testgroup.items()) == {
+ ("curve", "curve25519"),
+ ("type", "XdhComp"),
+ }
private_key = X25519PrivateKey.from_private_bytes(
binascii.unhexlify(wycheproof.testcase["private"])
diff --git a/tests/wycheproof/test_x448.py b/tests/wycheproof/test_x448.py
new file mode 100644
index 000000000..fcac80996
--- /dev/null
+++ b/tests/wycheproof/test_x448.py
@@ -0,0 +1,50 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+import pytest
+
+from cryptography.hazmat.primitives.asymmetric.x448 import (
+ X448PrivateKey,
+ X448PublicKey,
+)
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.x448_supported(),
+ skip_message="Requires OpenSSL with X448 support",
+)
+@pytest.mark.wycheproof_tests("x448_test.json")
+def test_x448(backend, wycheproof):
+ assert set(wycheproof.testgroup.items()) == {
+ ("curve", "curve448"),
+ ("type", "XdhComp"),
+ }
+
+ private_key = X448PrivateKey.from_private_bytes(
+ binascii.unhexlify(wycheproof.testcase["private"])
+ )
+ public_key_bytes = binascii.unhexlify(wycheproof.testcase["public"])
+ if len(public_key_bytes) == 57:
+ assert wycheproof.acceptable
+ assert wycheproof.has_flag("NonCanonicalPublic")
+ with pytest.raises(ValueError):
+ X448PublicKey.from_public_bytes(public_key_bytes)
+ return
+
+ public_key = X448PublicKey.from_public_bytes(public_key_bytes)
+
+ assert wycheproof.valid or wycheproof.acceptable
+
+ expected = binascii.unhexlify(wycheproof.testcase["shared"])
+ if expected == b"\x00" * 56:
+ assert wycheproof.acceptable
+ # OpenSSL returns an error on all zeros shared key
+ with pytest.raises(ValueError):
+ private_key.exchange(public_key)
+ else:
+ assert private_key.exchange(public_key) == expected
diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py
index 3abaff506..b64940242 100644
--- a/tests/x509/test_ocsp.py
+++ b/tests/x509/test_ocsp.py
@@ -13,7 +13,7 @@ import pytest
from cryptography import x509
from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.primitives import hashes, serialization
-from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.primitives.asymmetric import ec, ed25519, ed448
from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
from cryptography.x509 import ocsp
@@ -24,51 +24,52 @@ from ..utils import load_vectors_from_file
def _load_data(filename, loader):
return load_vectors_from_file(
- filename=filename,
- loader=lambda data: loader(data.read()),
- mode="rb"
+ filename=filename, loader=lambda data: loader(data.read()), mode="rb"
)
def _cert_and_issuer():
from cryptography.hazmat.backends.openssl.backend import backend
+
cert = _load_cert(
os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
issuer = _load_cert(
os.path.join("x509", "rapidssl_sha256_ca_g3.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
return cert, issuer
-def _generate_root():
+def _generate_root(private_key=None, algorithm=hashes.SHA256()):
from cryptography.hazmat.backends.openssl.backend import backend
- private_key = EC_KEY_SECP256R1.private_key(backend)
- subject = x509.Name([
- x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(x509.NameOID.COMMON_NAME, u'Cryptography CA'),
- ])
-
- builder = x509.CertificateBuilder().serial_number(
- 123456789
- ).issuer_name(
- subject
- ).subject_name(
- subject
- ).public_key(
- private_key.public_key()
- ).not_valid_before(
- datetime.datetime.now()
- ).not_valid_after(
- datetime.datetime.now() + datetime.timedelta(days=3650)
+ if private_key is None:
+ private_key = EC_KEY_SECP256R1.private_key(backend)
+
+ subject = x509.Name(
+ [
+ x509.NameAttribute(x509.NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(x509.NameOID.COMMON_NAME, u"Cryptography CA"),
+ ]
)
- cert = builder.sign(private_key, hashes.SHA256(), backend)
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(123456789)
+ .issuer_name(subject)
+ .subject_name(subject)
+ .public_key(private_key.public_key())
+ .not_valid_before(datetime.datetime.now())
+ .not_valid_after(
+ datetime.datetime.now() + datetime.timedelta(days=3650)
+ )
+ )
+
+ cert = builder.sign(private_key, algorithm, backend)
return cert, private_key
@@ -82,10 +83,12 @@ class TestOCSPRequest(object):
os.path.join("x509", "ocsp", "req-sha1.der"),
ocsp.load_der_ocsp_request,
)
- assert req.issuer_name_hash == (b"8\xcaF\x8c\x07D\x8d\xf4\x81\x96"
- b"\xc7mmLpQ\x9e`\xa7\xbd")
- assert req.issuer_key_hash == (b"yu\xbb\x84:\xcb,\xdez\t\xbe1"
- b"\x1bC\xbc\x1c*MSX")
+ assert req.issuer_name_hash == (
+ b"8\xcaF\x8c\x07D\x8d\xf4\x81\x96" b"\xc7mmLpQ\x9e`\xa7\xbd"
+ )
+ assert req.issuer_key_hash == (
+ b"yu\xbb\x84:\xcb,\xdez\t\xbe1" b"\x1bC\xbc\x1c*MSX"
+ )
assert isinstance(req.hash_algorithm, hashes.SHA1)
assert req.serial_number == int(
"98D9E5C0B4C373552DF77C5D0F1EB5128E4945F9", 16
@@ -123,7 +126,7 @@ class TestOCSPRequest(object):
req_bytes = load_vectors_from_file(
filename=os.path.join("x509", "ocsp", "req-sha1.der"),
loader=lambda data: data.read(),
- mode="rb"
+ mode="rb",
)
req = ocsp.load_der_ocsp_request(req_bytes)
assert req.public_bytes(serialization.Encoding.DER) == req_bytes
@@ -194,16 +197,14 @@ class TestOCSPRequestBuilder(object):
[
[x509.OCSPNonce(b"0000"), False],
[x509.OCSPNonce(b"\x00\x01\x02"), True],
- ]
+ ],
)
def test_create_ocsp_request_with_extension(self, ext, critical):
cert, issuer = _cert_and_issuer()
builder = ocsp.OCSPRequestBuilder()
builder = builder.add_certificate(
cert, issuer, hashes.SHA1()
- ).add_extension(
- ext, critical
- )
+ ).add_extension(ext, critical)
req = builder.build()
assert len(req.extensions) == 1
assert req.extensions[0].value == ext
@@ -217,13 +218,25 @@ class TestOCSPResponseBuilder(object):
time = datetime.datetime.now()
builder = ocsp.OCSPResponseBuilder()
builder = builder.add_response(
- cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD, time,
- time, None, None
+ cert,
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.GOOD,
+ time,
+ time,
+ None,
+ None,
)
with pytest.raises(ValueError):
builder.add_response(
- cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD, time,
- time, None, None
+ cert,
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.GOOD,
+ time,
+ time,
+ None,
+ None,
)
def test_invalid_add_response(self):
@@ -233,28 +246,58 @@ class TestOCSPResponseBuilder(object):
builder = ocsp.OCSPResponseBuilder()
with pytest.raises(TypeError):
builder.add_response(
- 'bad', issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
- time, time, None, None
+ "bad",
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.GOOD,
+ time,
+ time,
+ None,
+ None,
)
with pytest.raises(TypeError):
builder.add_response(
- cert, 'bad', hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
- time, time, None, None
+ cert,
+ "bad",
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.GOOD,
+ time,
+ time,
+ None,
+ None,
)
with pytest.raises(ValueError):
builder.add_response(
- cert, issuer, 'notahash', ocsp.OCSPCertStatus.GOOD,
- time, time, None, None
+ cert,
+ issuer,
+ "notahash",
+ ocsp.OCSPCertStatus.GOOD,
+ time,
+ time,
+ None,
+ None,
)
with pytest.raises(TypeError):
builder.add_response(
- cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
- 'bad', time, None, None
+ cert,
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.GOOD,
+ "bad",
+ time,
+ None,
+ None,
)
with pytest.raises(TypeError):
builder.add_response(
- cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
- time, 'bad', None, None
+ cert,
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.GOOD,
+ time,
+ "bad",
+ None,
+ None,
)
with pytest.raises(TypeError):
@@ -263,28 +306,58 @@ class TestOCSPResponseBuilder(object):
)
with pytest.raises(ValueError):
builder.add_response(
- cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
- time, time, time, None
+ cert,
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.GOOD,
+ time,
+ time,
+ time,
+ None,
)
with pytest.raises(ValueError):
builder.add_response(
- cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.GOOD,
- time, time, None, reason
+ cert,
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.GOOD,
+ time,
+ time,
+ None,
+ reason,
)
with pytest.raises(TypeError):
builder.add_response(
- cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.REVOKED,
- time, time, None, reason
+ cert,
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.REVOKED,
+ time,
+ time,
+ None,
+ reason,
)
with pytest.raises(TypeError):
builder.add_response(
- cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.REVOKED,
- time, time, time, 0
+ cert,
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.REVOKED,
+ time,
+ time,
+ time,
+ 0,
)
with pytest.raises(ValueError):
builder.add_response(
- cert, issuer, hashes.SHA256(), ocsp.OCSPCertStatus.REVOKED,
- time, time, time - datetime.timedelta(days=36500), None
+ cert,
+ issuer,
+ hashes.SHA256(),
+ ocsp.OCSPCertStatus.REVOKED,
+ time,
+ time,
+ time - datetime.timedelta(days=36500),
+ None,
)
def test_invalid_certificates(self):
@@ -292,9 +365,9 @@ class TestOCSPResponseBuilder(object):
with pytest.raises(ValueError):
builder.certificates([])
with pytest.raises(TypeError):
- builder.certificates(['notacert'])
+ builder.certificates(["notacert"])
with pytest.raises(TypeError):
- builder.certificates('invalid')
+ builder.certificates("invalid")
_, issuer = _cert_and_issuer()
builder = builder.certificates([issuer])
@@ -305,9 +378,9 @@ class TestOCSPResponseBuilder(object):
builder = ocsp.OCSPResponseBuilder()
cert, _ = _cert_and_issuer()
with pytest.raises(TypeError):
- builder.responder_id(ocsp.OCSPResponderEncoding.HASH, 'invalid')
+ builder.responder_id(ocsp.OCSPResponderEncoding.HASH, "invalid")
with pytest.raises(TypeError):
- builder.responder_id('notanenum', cert)
+ builder.responder_id("notanenum", cert)
builder = builder.responder_id(ocsp.OCSPResponderEncoding.NAME, cert)
with pytest.raises(ValueError):
@@ -335,8 +408,14 @@ class TestOCSPResponseBuilder(object):
this_update = current_time - datetime.timedelta(days=1)
next_update = this_update + datetime.timedelta(days=7)
builder = builder.add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
- next_update, None, None
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.GOOD,
+ this_update,
+ next_update,
+ None,
+ None,
)
with pytest.raises(ValueError):
builder.sign(private_key, hashes.SHA256())
@@ -351,11 +430,17 @@ class TestOCSPResponseBuilder(object):
builder = builder.responder_id(
ocsp.OCSPResponderEncoding.NAME, root_cert
).add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
- next_update, None, None
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.GOOD,
+ this_update,
+ next_update,
+ None,
+ None,
)
with pytest.raises(TypeError):
- builder.sign(private_key, 'notahash')
+ builder.sign(private_key, "notahash")
def test_sign_good_cert(self):
builder = ocsp.OCSPResponseBuilder()
@@ -367,15 +452,23 @@ class TestOCSPResponseBuilder(object):
builder = builder.responder_id(
ocsp.OCSPResponderEncoding.NAME, root_cert
).add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
- next_update, None, None
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.GOOD,
+ this_update,
+ next_update,
+ None,
+ None,
)
resp = builder.sign(private_key, hashes.SHA256())
assert resp.responder_name == root_cert.subject
assert resp.responder_key_hash is None
assert (current_time - resp.produced_at).total_seconds() < 10
- assert (resp.signature_algorithm_oid ==
- x509.SignatureAlgorithmOID.ECDSA_WITH_SHA256)
+ assert (
+ resp.signature_algorithm_oid
+ == x509.SignatureAlgorithmOID.ECDSA_WITH_SHA256
+ )
assert resp.certificate_status == ocsp.OCSPCertStatus.GOOD
assert resp.revocation_time is None
assert resp.revocation_reason is None
@@ -396,8 +489,14 @@ class TestOCSPResponseBuilder(object):
builder = builder.responder_id(
ocsp.OCSPResponderEncoding.NAME, root_cert
).add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.REVOKED,
- this_update, next_update, revoked_date, None
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.REVOKED,
+ this_update,
+ next_update,
+ revoked_date,
+ None,
)
resp = builder.sign(private_key, hashes.SHA256())
assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
@@ -416,13 +515,19 @@ class TestOCSPResponseBuilder(object):
current_time = datetime.datetime.utcnow().replace(microsecond=0)
this_update = current_time - datetime.timedelta(days=1)
next_update = this_update + datetime.timedelta(days=7)
- builder = builder.responder_id(
- ocsp.OCSPResponderEncoding.NAME, root_cert
- ).add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
- next_update, None, None
- ).certificates(
- [root_cert]
+ builder = (
+ builder.responder_id(ocsp.OCSPResponderEncoding.NAME, root_cert)
+ .add_response(
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.GOOD,
+ this_update,
+ next_update,
+ None,
+ None,
+ )
+ .certificates([root_cert])
)
resp = builder.sign(private_key, hashes.SHA256())
assert resp.certificates == [root_cert]
@@ -437,8 +542,14 @@ class TestOCSPResponseBuilder(object):
builder = builder.responder_id(
ocsp.OCSPResponderEncoding.NAME, root_cert
).add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.REVOKED,
- this_update, None, revoked_date, None
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.REVOKED,
+ this_update,
+ None,
+ revoked_date,
+ None,
)
resp = builder.sign(private_key, hashes.SHA256())
assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
@@ -461,9 +572,14 @@ class TestOCSPResponseBuilder(object):
builder = builder.responder_id(
ocsp.OCSPResponderEncoding.NAME, root_cert
).add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.REVOKED,
- this_update, next_update, revoked_date,
- x509.ReasonFlags.key_compromise
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.REVOKED,
+ this_update,
+ next_update,
+ revoked_date,
+ x509.ReasonFlags.key_compromise,
)
resp = builder.sign(private_key, hashes.SHA256())
assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
@@ -485,13 +601,19 @@ class TestOCSPResponseBuilder(object):
builder = builder.responder_id(
ocsp.OCSPResponderEncoding.HASH, root_cert
).add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
- next_update, None, None
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.GOOD,
+ this_update,
+ next_update,
+ None,
+ None,
)
resp = builder.sign(private_key, hashes.SHA256())
assert resp.responder_name is None
assert resp.responder_key_hash == (
- b'\x8ca\x94\xe0\x948\xed\x89\xd8\xd4N\x89p\t\xd6\xf9^_\xec}'
+ b"\x8ca\x94\xe0\x948\xed\x89\xd8\xd4N\x89p\t\xd6\xf9^_\xec}"
)
private_key.public_key().verify(
resp.signature, resp.tbs_response_bytes, ec.ECDSA(hashes.SHA256())
@@ -507,10 +629,17 @@ class TestOCSPResponseBuilder(object):
builder = builder.responder_id(
ocsp.OCSPResponderEncoding.HASH, root_cert
).add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
- next_update, None, None
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.GOOD,
+ this_update,
+ next_update,
+ None,
+ None,
)
from cryptography.hazmat.backends.openssl.backend import backend
+
diff_key = ec.generate_private_key(ec.SECP256R1(), backend)
with pytest.raises(ValueError):
builder.sign(diff_key, hashes.SHA256())
@@ -522,13 +651,19 @@ class TestOCSPResponseBuilder(object):
current_time = datetime.datetime.utcnow().replace(microsecond=0)
this_update = current_time - datetime.timedelta(days=1)
next_update = this_update + datetime.timedelta(days=7)
- builder = builder.responder_id(
- ocsp.OCSPResponderEncoding.HASH, root_cert
- ).add_response(
- cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.GOOD, this_update,
- next_update, None, None
- ).add_extension(
- x509.OCSPNonce(b"012345"), False
+ builder = (
+ builder.responder_id(ocsp.OCSPResponderEncoding.HASH, root_cert)
+ .add_response(
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.GOOD,
+ this_update,
+ next_update,
+ None,
+ None,
+ )
+ .add_extension(x509.OCSPNonce(b"012345"), False)
)
resp = builder.sign(private_key, hashes.SHA256())
assert len(resp.extensions) == 1
@@ -546,7 +681,7 @@ class TestOCSPResponseBuilder(object):
(ocsp.OCSPResponseStatus.TRY_LATER, b"0\x03\n\x01\x03"),
(ocsp.OCSPResponseStatus.SIG_REQUIRED, b"0\x03\n\x01\x05"),
(ocsp.OCSPResponseStatus.UNAUTHORIZED, b"0\x03\n\x01\x06"),
- ]
+ ],
)
def test_build_non_successful_statuses(self, status, der):
resp = ocsp.OCSPResponseBuilder.build_unsuccessful(status)
@@ -564,6 +699,92 @@ class TestOCSPResponseBuilder(object):
)
+class TestSignedCertificateTimestampsExtension(object):
+ def test_init(self):
+ with pytest.raises(TypeError):
+ x509.SignedCertificateTimestamps([object()])
+
+ def test_repr(self):
+ assert repr(x509.SignedCertificateTimestamps([])) == (
+ "<SignedCertificateTimestamps([])>"
+ )
+
+ @pytest.mark.supported(
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
+ )
+ def test_eq(self, backend):
+ sct1 = (
+ _load_data(
+ os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+ ocsp.load_der_ocsp_response,
+ )
+ .single_extensions.get_extension_for_class(
+ x509.SignedCertificateTimestamps
+ )
+ .value
+ )
+ sct2 = (
+ _load_data(
+ os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+ ocsp.load_der_ocsp_response,
+ )
+ .single_extensions.get_extension_for_class(
+ x509.SignedCertificateTimestamps
+ )
+ .value
+ )
+ assert sct1 == sct2
+
+ @pytest.mark.supported(
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
+ )
+ def test_ne(self, backend):
+ sct1 = (
+ _load_data(
+ os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+ ocsp.load_der_ocsp_response,
+ )
+ .single_extensions.get_extension_for_class(
+ x509.SignedCertificateTimestamps
+ )
+ .value
+ )
+ sct2 = x509.SignedCertificateTimestamps([])
+ assert sct1 != sct2
+ assert sct1 != object()
+
+ @pytest.mark.supported(
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
+ )
+ def test_hash(self, backend):
+ sct1 = (
+ _load_data(
+ os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+ ocsp.load_der_ocsp_response,
+ )
+ .single_extensions.get_extension_for_class(
+ x509.SignedCertificateTimestamps
+ )
+ .value
+ )
+ sct2 = (
+ _load_data(
+ os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+ ocsp.load_der_ocsp_response,
+ )
+ .single_extensions.get_extension_for_class(
+ x509.SignedCertificateTimestamps
+ )
+ .value
+ )
+ sct3 = x509.SignedCertificateTimestamps([])
+ assert hash(sct1) == hash(sct2)
+ assert hash(sct1) != hash(sct3)
+
+
class TestOCSPResponse(object):
def test_bad_response(self):
with pytest.raises(ValueError):
@@ -575,14 +796,17 @@ class TestOCSPResponse(object):
ocsp.load_der_ocsp_response,
)
from cryptography.hazmat.backends.openssl.backend import backend
+
issuer = _load_cert(
os.path.join("x509", "letsencryptx3.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert resp.response_status == ocsp.OCSPResponseStatus.SUCCESSFUL
- assert (resp.signature_algorithm_oid ==
- x509.SignatureAlgorithmOID.RSA_WITH_SHA256)
+ assert (
+ resp.signature_algorithm_oid
+ == x509.SignatureAlgorithmOID.RSA_WITH_SHA256
+ )
assert isinstance(resp.signature_hash_algorithm, hashes.SHA256)
assert resp.signature == base64.b64decode(
b"I9KUlyLV/2LbNCVu1BQphxdNlU/jBzXsPYVscPjW5E93pCrSO84GkIWoOJtqsnt"
@@ -603,7 +827,7 @@ class TestOCSPResponse(object):
resp.signature,
resp.tbs_response_bytes,
PKCS1v15(),
- resp.signature_hash_algorithm
+ resp.signature_hash_algorithm,
)
assert resp.certificates == []
assert resp.responder_key_hash is None
@@ -615,15 +839,22 @@ class TestOCSPResponse(object):
assert resp.this_update == datetime.datetime(2018, 8, 30, 11, 0)
assert resp.next_update == datetime.datetime(2018, 9, 6, 11, 0)
assert resp.issuer_key_hash == (
- b'\xa8Jjc\x04}\xdd\xba\xe6\xd19\xb7\xa6Ee\xef\xf3\xa8\xec\xa1'
+ b"\xa8Jjc\x04}\xdd\xba\xe6\xd19\xb7\xa6Ee\xef\xf3\xa8\xec\xa1"
)
assert resp.issuer_name_hash == (
- b'~\xe6j\xe7r\x9a\xb3\xfc\xf8\xa2 dl\x16\xa1-`q\x08]'
+ b"~\xe6j\xe7r\x9a\xb3\xfc\xf8\xa2 dl\x16\xa1-`q\x08]"
)
assert isinstance(resp.hash_algorithm, hashes.SHA1)
assert resp.serial_number == 271024907440004808294641238224534273948400
assert len(resp.extensions) == 0
+ def test_load_multi_valued_response(self):
+ with pytest.raises(ValueError):
+ _load_data(
+ os.path.join("x509", "ocsp", "ocsp-army.deps.mil-resp.der"),
+ ocsp.load_der_ocsp_response,
+ )
+
def test_load_unauthorized(self):
resp = _load_data(
os.path.join("x509", "ocsp", "resp-unauthorized.der"),
@@ -705,7 +936,7 @@ class TestOCSPResponse(object):
)
assert resp.responder_name is None
assert resp.responder_key_hash == (
- b'\x0f\x80a\x1c\x821a\xd5/(\xe7\x8dF8\xb4,\xe1\xc6\xd9\xe2'
+ b"\x0f\x80a\x1c\x821a\xd5/(\xe7\x8dF8\xb4,\xe1\xc6\xd9\xe2"
)
def test_load_revoked_reason(self):
@@ -739,7 +970,7 @@ class TestOCSPResponse(object):
resp_bytes = load_vectors_from_file(
filename=os.path.join("x509", "ocsp", "resp-revoked.der"),
loader=lambda data: data.read(),
- mode="rb"
+ mode="rb",
)
resp = ocsp.load_der_ocsp_response(resp_bytes)
assert resp.public_bytes(serialization.Encoding.DER) == resp_bytes
@@ -753,3 +984,161 @@ class TestOCSPResponse(object):
resp.public_bytes("invalid")
with pytest.raises(ValueError):
resp.public_bytes(serialization.Encoding.PEM)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
+ )
+ def test_single_extensions_sct(self, backend):
+ resp = _load_data(
+ os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+ ocsp.load_der_ocsp_response,
+ )
+ assert len(resp.single_extensions) == 1
+ ext = resp.single_extensions[0]
+ assert ext.oid == x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.5")
+ assert len(ext.value) == 4
+ log_ids = [base64.b64encode(sct.log_id) for sct in ext.value]
+ assert log_ids == [
+ b"RJRlLrDuzq/EQAfYqP4owNrmgr7YyzG1P9MzlrW2gag=",
+ b"b1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RM=",
+ b"u9nfvB+KcbWTlCOXqpJ7RzhXlQqrUugakJZkNo4e0YU=",
+ b"7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/cs=",
+ ]
+
+ @pytest.mark.supported(
+ only_if=lambda backend: (
+ not backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER
+ ),
+ skip_message="Requires OpenSSL < 1.1.0f",
+ )
+ def test_skips_single_extensions_scts_if_unsupported(self, backend):
+ resp = _load_data(
+ os.path.join("x509", "ocsp", "resp-sct-extension.der"),
+ ocsp.load_der_ocsp_response,
+ )
+ with pytest.raises(x509.ExtensionNotFound):
+ resp.single_extensions.get_extension_for_class(
+ x509.SignedCertificateTimestamps
+ )
+
+ ext = resp.single_extensions.get_extension_for_oid(
+ x509.ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS
+ )
+ assert isinstance(ext.value, x509.UnrecognizedExtension)
+
+ def test_single_extensions(self, backend):
+ resp = _load_data(
+ os.path.join("x509", "ocsp", "resp-single-extension-reason.der"),
+ ocsp.load_der_ocsp_response,
+ )
+ assert len(resp.single_extensions) == 1
+ ext = resp.single_extensions[0]
+ assert ext.oid == x509.CRLReason.oid
+ assert ext.value == x509.CRLReason(x509.ReasonFlags.unspecified)
+
+
+class TestOCSPEdDSA(object):
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support / OCSP",
+ )
+ def test_invalid_algorithm(self, backend):
+ builder = ocsp.OCSPResponseBuilder()
+ cert, issuer = _cert_and_issuer()
+ private_key = ed25519.Ed25519PrivateKey.generate()
+ root_cert, _ = _generate_root(private_key, None)
+ current_time = datetime.datetime.utcnow().replace(microsecond=0)
+ this_update = current_time - datetime.timedelta(days=1)
+ next_update = this_update + datetime.timedelta(days=7)
+ revoked_date = this_update - datetime.timedelta(days=300)
+ builder = builder.responder_id(
+ ocsp.OCSPResponderEncoding.NAME, root_cert
+ ).add_response(
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.REVOKED,
+ this_update,
+ next_update,
+ revoked_date,
+ x509.ReasonFlags.key_compromise,
+ )
+ with pytest.raises(ValueError):
+ builder.sign(private_key, hashes.SHA256())
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support / OCSP",
+ )
+ def test_sign_ed25519(self, backend):
+ builder = ocsp.OCSPResponseBuilder()
+ cert, issuer = _cert_and_issuer()
+ private_key = ed25519.Ed25519PrivateKey.generate()
+ root_cert, _ = _generate_root(private_key, None)
+ current_time = datetime.datetime.utcnow().replace(microsecond=0)
+ this_update = current_time - datetime.timedelta(days=1)
+ next_update = this_update + datetime.timedelta(days=7)
+ revoked_date = this_update - datetime.timedelta(days=300)
+ builder = builder.responder_id(
+ ocsp.OCSPResponderEncoding.NAME, root_cert
+ ).add_response(
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.REVOKED,
+ this_update,
+ next_update,
+ revoked_date,
+ x509.ReasonFlags.key_compromise,
+ )
+ resp = builder.sign(private_key, None)
+ assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
+ assert resp.revocation_time == revoked_date
+ assert resp.revocation_reason is x509.ReasonFlags.key_compromise
+ assert resp.this_update == this_update
+ assert resp.next_update == next_update
+ assert resp.signature_hash_algorithm is None
+ assert (
+ resp.signature_algorithm_oid == x509.SignatureAlgorithmOID.ED25519
+ )
+ private_key.public_key().verify(
+ resp.signature, resp.tbs_response_bytes
+ )
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support / OCSP",
+ )
+ def test_sign_ed448(self, backend):
+ builder = ocsp.OCSPResponseBuilder()
+ cert, issuer = _cert_and_issuer()
+ private_key = ed448.Ed448PrivateKey.generate()
+ root_cert, _ = _generate_root(private_key, None)
+ current_time = datetime.datetime.utcnow().replace(microsecond=0)
+ this_update = current_time - datetime.timedelta(days=1)
+ next_update = this_update + datetime.timedelta(days=7)
+ revoked_date = this_update - datetime.timedelta(days=300)
+ builder = builder.responder_id(
+ ocsp.OCSPResponderEncoding.NAME, root_cert
+ ).add_response(
+ cert,
+ issuer,
+ hashes.SHA1(),
+ ocsp.OCSPCertStatus.REVOKED,
+ this_update,
+ next_update,
+ revoked_date,
+ x509.ReasonFlags.key_compromise,
+ )
+ resp = builder.sign(private_key, None)
+ assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED
+ assert resp.revocation_time == revoked_date
+ assert resp.revocation_reason is x509.ReasonFlags.key_compromise
+ assert resp.this_update == this_update
+ assert resp.next_update == next_update
+ assert resp.signature_hash_algorithm is None
+ assert resp.signature_algorithm_oid == x509.SignatureAlgorithmOID.ED448
+ private_key.public_key().verify(
+ resp.signature, resp.tbs_response_bytes
+ )
diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py
index c8c863fb0..146619b9a 100644
--- a/tests/x509/test_x509.py
+++ b/tests/x509/test_x509.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
@@ -5,12 +6,12 @@
from __future__ import absolute_import, division, print_function
import binascii
+import collections
+import copy
import datetime
import ipaddress
import os
-from asn1crypto.x509 import Certificate
-
import pytest
import pytz
@@ -19,25 +20,54 @@ import six
from cryptography import utils, x509
from cryptography.exceptions import UnsupportedAlgorithm
+from cryptography.hazmat._der import (
+ BIT_STRING,
+ CONSTRUCTED,
+ CONTEXT_SPECIFIC,
+ DERReader,
+ GENERALIZED_TIME,
+ INTEGER,
+ OBJECT_IDENTIFIER,
+ PRINTABLE_STRING,
+ SEQUENCE,
+ SET,
+ UTC_TIME,
+)
from cryptography.hazmat.backends.interfaces import (
- DSABackend, EllipticCurveBackend, RSABackend, X509Backend
+ DSABackend,
+ EllipticCurveBackend,
+ RSABackend,
+ X509Backend,
)
from cryptography.hazmat.primitives import hashes, serialization
-from cryptography.hazmat.primitives.asymmetric import dsa, ec, padding, rsa
+from cryptography.hazmat.primitives.asymmetric import (
+ dh,
+ dsa,
+ ec,
+ ed25519,
+ ed448,
+ padding,
+ rsa,
+)
from cryptography.hazmat.primitives.asymmetric.utils import (
- decode_dss_signature
+ decode_dss_signature,
)
+from cryptography.utils import int_from_bytes
from cryptography.x509.name import _ASN1Type
from cryptography.x509.oid import (
- AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID,
- NameOID, SignatureAlgorithmOID
+ AuthorityInformationAccessOID,
+ ExtendedKeyUsageOID,
+ ExtensionOID,
+ NameOID,
+ SignatureAlgorithmOID,
+ SubjectInformationAccessOID,
)
from ..hazmat.primitives.fixtures_dsa import DSA_KEY_2048
from ..hazmat.primitives.fixtures_ec import EC_KEY_SECP256R1
from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512
from ..hazmat.primitives.test_ec import _skip_curve_unsupported
-from ..utils import load_vectors_from_file
+from ..utils import load_nist_vectors, load_vectors_from_file
@utils.register_interface(x509.ExtensionType)
@@ -57,18 +87,64 @@ def _load_cert(filename, loader, backend):
cert = load_vectors_from_file(
filename=filename,
loader=lambda pemfile: loader(pemfile.read(), backend),
- mode="rb"
+ mode="rb",
)
return cert
+ParsedCertificate = collections.namedtuple(
+ "ParsedCertificate",
+ ["not_before_tag", "not_after_tag", "issuer", "subject"],
+)
+
+
+def _parse_cert(der):
+ # See the Certificate structured, defined in RFC 5280.
+ with DERReader(der).read_single_element(SEQUENCE) as cert:
+ tbs_cert = cert.read_element(SEQUENCE)
+ # Skip outer signature algorithm
+ _ = cert.read_element(SEQUENCE)
+ # Skip signature
+ _ = cert.read_element(BIT_STRING)
+
+ with tbs_cert:
+ # Skip version
+ _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 0)
+ # Skip serialNumber
+ _ = tbs_cert.read_element(INTEGER)
+ # Skip inner signature algorithm
+ _ = tbs_cert.read_element(SEQUENCE)
+ issuer = tbs_cert.read_element(SEQUENCE)
+ validity = tbs_cert.read_element(SEQUENCE)
+ subject = tbs_cert.read_element(SEQUENCE)
+ # Skip subjectPublicKeyInfo
+ _ = tbs_cert.read_element(SEQUENCE)
+ # Skip issuerUniqueID
+ _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 1)
+ # Skip subjectUniqueID
+ _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 2)
+ # Skip extensions
+ _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 3)
+
+ with validity:
+ not_before_tag, _ = validity.read_any_element()
+ not_after_tag, _ = validity.read_any_element()
+
+ return ParsedCertificate(
+ not_before_tag=not_before_tag,
+ not_after_tag=not_after_tag,
+ issuer=issuer,
+ subject=subject,
+ )
+
+
@pytest.mark.requires_backend_interface(interface=X509Backend)
class TestCertificateRevocationList(object):
def test_load_pem_crl(self, backend):
crl = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
assert isinstance(crl, x509.CertificateRevocationList)
@@ -76,15 +152,15 @@ class TestCertificateRevocationList(object):
assert fingerprint == b"3234b0cb4c0cedf6423724b736729dcfc9e441ef"
assert isinstance(crl.signature_hash_algorithm, hashes.SHA256)
assert (
- crl.signature_algorithm_oid ==
- SignatureAlgorithmOID.RSA_WITH_SHA256
+ crl.signature_algorithm_oid
+ == SignatureAlgorithmOID.RSA_WITH_SHA256
)
def test_load_der_crl(self, backend):
crl = _load_cert(
os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
x509.load_der_x509_crl,
- backend
+ backend,
)
assert isinstance(crl, x509.CertificateRevocationList)
@@ -106,48 +182,48 @@ class TestCertificateRevocationList(object):
"x509", "custom", "crl_md2_unknown_crit_entry_ext.pem"
),
x509.load_pem_x509_crl,
- backend
+ backend,
)
with pytest.raises(UnsupportedAlgorithm):
- crl.signature_hash_algorithm()
+ crl.signature_hash_algorithm()
def test_issuer(self, backend):
crl = _load_cert(
os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
x509.load_der_x509_crl,
- backend
+ backend,
)
assert isinstance(crl.issuer, x509.Name)
assert list(crl.issuer) == [
- x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US'),
+ x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
x509.NameAttribute(
- x509.OID_ORGANIZATION_NAME, u'Test Certificates 2011'
+ x509.OID_ORGANIZATION_NAME, u"Test Certificates 2011"
),
- x509.NameAttribute(x509.OID_COMMON_NAME, u'Good CA')
+ x509.NameAttribute(x509.OID_COMMON_NAME, u"Good CA"),
]
assert crl.issuer.get_attributes_for_oid(x509.OID_COMMON_NAME) == [
- x509.NameAttribute(x509.OID_COMMON_NAME, u'Good CA')
+ x509.NameAttribute(x509.OID_COMMON_NAME, u"Good CA")
]
def test_equality(self, backend):
crl1 = _load_cert(
os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
x509.load_der_x509_crl,
- backend
+ backend,
)
crl2 = _load_cert(
os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
x509.load_der_x509_crl,
- backend
+ backend,
)
crl3 = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
assert crl1 == crl2
@@ -158,7 +234,7 @@ class TestCertificateRevocationList(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
assert isinstance(crl.next_update, datetime.datetime)
@@ -171,7 +247,7 @@ class TestCertificateRevocationList(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
for r in crl:
@@ -183,9 +259,10 @@ class TestCertificateRevocationList(object):
def test_get_revoked_certificate_by_serial_number(self, backend):
crl = _load_cert(
os.path.join(
- "x509", "PKITS_data", "crls", "LongSerialNumberCACRL.crl"),
+ "x509", "PKITS_data", "crls", "LongSerialNumberCACRL.crl"
+ ),
x509.load_der_x509_crl,
- backend
+ backend,
)
serial_number = 725064303890588110203033396814564464046290047507
revoked = crl.get_revoked_certificate_by_serial_number(serial_number)
@@ -201,7 +278,7 @@ class TestCertificateRevocationList(object):
revoked = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)[11]
assert revoked.revocation_date == datetime.datetime(2015, 1, 1, 0, 0)
assert revoked.serial_number == 11
@@ -210,7 +287,7 @@ class TestCertificateRevocationList(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_ian_aia_aki.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
crl_number = crl.extensions.get_extension_for_oid(
@@ -228,40 +305,40 @@ class TestCertificateRevocationList(object):
assert crl_number.value == x509.CRLNumber(1)
assert crl_number.critical is False
assert aki.value == x509.AuthorityKeyIdentifier(
- key_identifier=(
- b'yu\xbb\x84:\xcb,\xdez\t\xbe1\x1bC\xbc\x1c*MSX'
- ),
+ key_identifier=(b"yu\xbb\x84:\xcb,\xdez\t\xbe1\x1bC\xbc\x1c*MSX"),
authority_cert_issuer=None,
- authority_cert_serial_number=None
+ authority_cert_serial_number=None,
+ )
+ assert aia.value == x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.DNSName(u"cryptography.io"),
+ )
+ ]
+ )
+ assert ian.value == x509.IssuerAlternativeName(
+ [x509.UniformResourceIdentifier(u"https://cryptography.io")]
)
- assert aia.value == x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.DNSName(u"cryptography.io")
- )
- ])
- assert ian.value == x509.IssuerAlternativeName([
- x509.UniformResourceIdentifier(u"https://cryptography.io"),
- ])
def test_delta_crl_indicator(self, backend):
crl = _load_cert(
os.path.join("x509", "custom", "crl_delta_crl_indicator.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
dci = crl.extensions.get_extension_for_oid(
ExtensionOID.DELTA_CRL_INDICATOR
)
assert dci.value == x509.DeltaCRLIndicator(12345678901234567890)
- assert dci.critical is False
+ assert dci.critical is True
def test_signature(self, backend):
crl = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
assert crl.signature == binascii.unhexlify(
@@ -280,31 +357,36 @@ class TestCertificateRevocationList(object):
crl = _load_cert(
os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
x509.load_der_x509_crl,
- backend
+ backend,
)
ca_cert = _load_cert(
os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
ca_cert.public_key().verify(
- crl.signature, crl.tbs_certlist_bytes,
- padding.PKCS1v15(), crl.signature_hash_algorithm
+ crl.signature,
+ crl.tbs_certlist_bytes,
+ padding.PKCS1v15(),
+ crl.signature_hash_algorithm,
)
def test_public_bytes_pem(self, backend):
crl = _load_cert(
os.path.join("x509", "custom", "crl_empty.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
# Encode it to PEM and load it back.
- crl = x509.load_pem_x509_crl(crl.public_bytes(
- encoding=serialization.Encoding.PEM,
- ), backend)
+ crl = x509.load_pem_x509_crl(
+ crl.public_bytes(
+ encoding=serialization.Encoding.PEM,
+ ),
+ backend,
+ )
assert len(crl) == 0
assert crl.last_update == datetime.datetime(2015, 12, 20, 23, 44, 47)
@@ -314,13 +396,16 @@ class TestCertificateRevocationList(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
# Encode it to DER and load it back.
- crl = x509.load_der_x509_crl(crl.public_bytes(
- encoding=serialization.Encoding.DER,
- ), backend)
+ crl = x509.load_der_x509_crl(
+ crl.public_bytes(
+ encoding=serialization.Encoding.DER,
+ ),
+ backend,
+ )
assert len(crl) == 12
assert crl.last_update == datetime.datetime(2015, 1, 1, 0, 0, 0)
@@ -339,10 +424,11 @@ class TestCertificateRevocationList(object):
x509.load_der_x509_crl,
serialization.Encoding.DER,
),
- ]
+ ],
)
- def test_public_bytes_match(self, cert_path, loader_func, encoding,
- backend):
+ def test_public_bytes_match(
+ self, cert_path, loader_func, encoding, backend
+ ):
crl_bytes = load_vectors_from_file(
cert_path, lambda pemfile: pemfile.read(), mode="rb"
)
@@ -354,22 +440,22 @@ class TestCertificateRevocationList(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_empty.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
with pytest.raises(TypeError):
- crl.public_bytes('NotAnEncoding')
+ crl.public_bytes("NotAnEncoding")
def test_verify_bad(self, backend):
crl = _load_cert(
os.path.join("x509", "custom", "invalid_signature.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
crt = _load_cert(
os.path.join("x509", "custom", "invalid_signature.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert not crl.is_signature_valid(crt.public_key())
@@ -378,12 +464,12 @@ class TestCertificateRevocationList(object):
crl = _load_cert(
os.path.join("x509", "custom", "valid_signature.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
crt = _load_cert(
os.path.join("x509", "custom", "valid_signature.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert crl.is_signature_valid(crt.public_key())
@@ -392,7 +478,7 @@ class TestCertificateRevocationList(object):
crl = _load_cert(
os.path.join("x509", "custom", "valid_signature.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
with pytest.raises(TypeError):
@@ -408,7 +494,7 @@ class TestRevokedCertificate(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
for i, rev in enumerate(crl):
@@ -424,14 +510,20 @@ class TestRevokedCertificate(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
exp_issuer = [
- x509.DirectoryName(x509.Name([
- x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
- x509.NameAttribute(x509.OID_COMMON_NAME, u"cryptography.io"),
- ]))
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
+ x509.NameAttribute(
+ x509.OID_COMMON_NAME, u"cryptography.io"
+ ),
+ ]
+ )
+ )
]
# First revoked cert doesn't have extensions, test if it is handled
@@ -451,16 +543,17 @@ class TestRevokedCertificate(object):
rev1 = crl[1]
assert isinstance(rev1.extensions, x509.Extensions)
- reason = rev1.extensions.get_extension_for_class(
- x509.CRLReason).value
+ reason = rev1.extensions.get_extension_for_class(x509.CRLReason).value
assert reason == x509.CRLReason(x509.ReasonFlags.unspecified)
issuer = rev1.extensions.get_extension_for_class(
- x509.CertificateIssuer).value
+ x509.CertificateIssuer
+ ).value
assert issuer == x509.CertificateIssuer(exp_issuer)
date = rev1.extensions.get_extension_for_class(
- x509.InvalidityDate).value
+ x509.InvalidityDate
+ ).value
assert date == x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0))
# Check if all reason flags can be found in the CRL.
@@ -480,7 +573,7 @@ class TestRevokedCertificate(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_empty.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
assert len(crl) == 0
@@ -488,7 +581,7 @@ class TestRevokedCertificate(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_dup_entry_ext.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
with pytest.raises(x509.DuplicateExtension):
@@ -500,7 +593,7 @@ class TestRevokedCertificate(object):
"x509", "custom", "crl_md2_unknown_crit_entry_ext.pem"
),
x509.load_pem_x509_crl,
- backend
+ backend,
)
ext = crl[0].extensions.get_extension_for_oid(
@@ -510,11 +603,9 @@ class TestRevokedCertificate(object):
def test_unsupported_reason(self, backend):
crl = _load_cert(
- os.path.join(
- "x509", "custom", "crl_unsupported_reason.pem"
- ),
+ os.path.join("x509", "custom", "crl_unsupported_reason.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
with pytest.raises(ValueError):
@@ -526,7 +617,7 @@ class TestRevokedCertificate(object):
"x509", "custom", "crl_inval_cert_issuer_entry_ext.pem"
),
x509.load_pem_x509_crl,
- backend
+ backend,
)
with pytest.raises(ValueError):
@@ -536,7 +627,7 @@ class TestRevokedCertificate(object):
crl = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
x509.load_pem_x509_crl,
- backend
+ backend,
)
with pytest.raises(IndexError):
@@ -553,21 +644,27 @@ class TestRevokedCertificate(object):
private_key = RSA_KEY_2048.private_key(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
)
for i in [2, 500, 3, 49, 7, 1]:
- revoked_cert = x509.RevokedCertificateBuilder().serial_number(
- i
- ).revocation_date(
- datetime.datetime(2012, 1, 1, 1, 1)
- ).build(backend)
+ revoked_cert = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(i)
+ .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+ .build(backend)
+ )
builder = builder.add_revoked_certificate(revoked_cert)
crl = builder.sign(private_key, hashes.SHA256(), backend)
assert crl[0].serial_number == 2
@@ -586,7 +683,7 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert isinstance(cert, x509.Certificate)
assert cert.serial_number == 11559813051657483483
@@ -597,44 +694,31 @@ class TestRSACertificate(object):
cert.signature_algorithm_oid == SignatureAlgorithmOID.RSA_WITH_SHA1
)
+ def test_negative_serial_number(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "custom", "negative_serial.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ assert cert.serial_number == -18008675309
+
def test_alternate_rsa_with_sha1_oid(self, backend):
cert = _load_cert(
os.path.join("x509", "alternate-rsa-sha1-oid.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert isinstance(cert.signature_hash_algorithm, hashes.SHA1)
assert (
- cert.signature_algorithm_oid ==
- SignatureAlgorithmOID._RSA_WITH_SHA1
+ cert.signature_algorithm_oid
+ == SignatureAlgorithmOID._RSA_WITH_SHA1
)
- def test_cert_serial_number(self, backend):
- cert = _load_cert(
- os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
- x509.load_der_x509_certificate,
- backend
- )
-
- with pytest.warns(utils.CryptographyDeprecationWarning):
- assert cert.serial == 2
- assert cert.serial_number == 2
-
- def test_cert_serial_warning(self, backend):
- cert = _load_cert(
- os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
- x509.load_der_x509_certificate,
- backend
- )
-
- with pytest.warns(utils.CryptographyDeprecationWarning):
- cert.serial
-
def test_load_der_cert(self, backend):
cert = _load_cert(
os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
assert isinstance(cert, x509.Certificate)
assert cert.serial_number == 2
@@ -646,7 +730,7 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert.signature == binascii.unhexlify(
b"8e0f72fcbebe4755abcaf76c8ce0bae17cde4db16291638e1b1ce04a93cdb4c"
@@ -665,7 +749,7 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert.tbs_certificate_bytes == binascii.unhexlify(
b"308202d8a003020102020900a06cb4b955f7f4db300d06092a864886f70d010"
@@ -694,132 +778,126 @@ class TestRSACertificate(object):
b"3040530030101ff"
)
cert.public_key().verify(
- cert.signature, cert.tbs_certificate_bytes,
- padding.PKCS1v15(), cert.signature_hash_algorithm
+ cert.signature,
+ cert.tbs_certificate_bytes,
+ padding.PKCS1v15(),
+ cert.signature_hash_algorithm,
)
def test_issuer(self, backend):
cert = _load_cert(
os.path.join(
- "x509", "PKITS_data", "certs",
- "Validpre2000UTCnotBeforeDateTest3EE.crt"
+ "x509",
+ "PKITS_data",
+ "certs",
+ "Validpre2000UTCnotBeforeDateTest3EE.crt",
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
issuer = cert.issuer
assert isinstance(issuer, x509.Name)
assert list(issuer) == [
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(
- NameOID.ORGANIZATION_NAME, u'Test Certificates 2011'
+ NameOID.ORGANIZATION_NAME, u"Test Certificates 2011"
),
- x509.NameAttribute(NameOID.COMMON_NAME, u'Good CA')
+ x509.NameAttribute(NameOID.COMMON_NAME, u"Good CA"),
]
assert issuer.get_attributes_for_oid(NameOID.COMMON_NAME) == [
- x509.NameAttribute(NameOID.COMMON_NAME, u'Good CA')
+ x509.NameAttribute(NameOID.COMMON_NAME, u"Good CA")
]
def test_all_issuer_name_types(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom",
- "all_supported_names.pem"
- ),
+ os.path.join("x509", "custom", "all_supported_names.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
issuer = cert.issuer
assert isinstance(issuer, x509.Name)
assert list(issuer) == [
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'CA'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Illinois'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Chicago'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Zero, LLC'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'One, LLC'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'common name 0'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'common name 1'),
- x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'OU 0'),
- x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'OU 1'),
- x509.NameAttribute(NameOID.DN_QUALIFIER, u'dnQualifier0'),
- x509.NameAttribute(NameOID.DN_QUALIFIER, u'dnQualifier1'),
- x509.NameAttribute(NameOID.SERIAL_NUMBER, u'123'),
- x509.NameAttribute(NameOID.SERIAL_NUMBER, u'456'),
- x509.NameAttribute(NameOID.TITLE, u'Title 0'),
- x509.NameAttribute(NameOID.TITLE, u'Title 1'),
- x509.NameAttribute(NameOID.SURNAME, u'Surname 0'),
- x509.NameAttribute(NameOID.SURNAME, u'Surname 1'),
- x509.NameAttribute(NameOID.GIVEN_NAME, u'Given Name 0'),
- x509.NameAttribute(NameOID.GIVEN_NAME, u'Given Name 1'),
- x509.NameAttribute(NameOID.PSEUDONYM, u'Incognito 0'),
- x509.NameAttribute(NameOID.PSEUDONYM, u'Incognito 1'),
- x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u'Last Gen'),
- x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u'Next Gen'),
- x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u'dc0'),
- x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u'dc1'),
- x509.NameAttribute(NameOID.EMAIL_ADDRESS, u'test0@test.local'),
- x509.NameAttribute(NameOID.EMAIL_ADDRESS, u'test1@test.local'),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"CA"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Illinois"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Chicago"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Zero, LLC"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"One, LLC"),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"common name 0"),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"common name 1"),
+ x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"OU 0"),
+ x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"OU 1"),
+ x509.NameAttribute(NameOID.DN_QUALIFIER, u"dnQualifier0"),
+ x509.NameAttribute(NameOID.DN_QUALIFIER, u"dnQualifier1"),
+ x509.NameAttribute(NameOID.SERIAL_NUMBER, u"123"),
+ x509.NameAttribute(NameOID.SERIAL_NUMBER, u"456"),
+ x509.NameAttribute(NameOID.TITLE, u"Title 0"),
+ x509.NameAttribute(NameOID.TITLE, u"Title 1"),
+ x509.NameAttribute(NameOID.SURNAME, u"Surname 0"),
+ x509.NameAttribute(NameOID.SURNAME, u"Surname 1"),
+ x509.NameAttribute(NameOID.GIVEN_NAME, u"Given Name 0"),
+ x509.NameAttribute(NameOID.GIVEN_NAME, u"Given Name 1"),
+ x509.NameAttribute(NameOID.PSEUDONYM, u"Incognito 0"),
+ x509.NameAttribute(NameOID.PSEUDONYM, u"Incognito 1"),
+ x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"Last Gen"),
+ x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"Next Gen"),
+ x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc0"),
+ x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc1"),
+ x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test0@test.local"),
+ x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test1@test.local"),
]
def test_subject(self, backend):
cert = _load_cert(
os.path.join(
- "x509", "PKITS_data", "certs",
- "Validpre2000UTCnotBeforeDateTest3EE.crt"
+ "x509",
+ "PKITS_data",
+ "certs",
+ "Validpre2000UTCnotBeforeDateTest3EE.crt",
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
subject = cert.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(
- NameOID.ORGANIZATION_NAME, u'Test Certificates 2011'
+ NameOID.ORGANIZATION_NAME, u"Test Certificates 2011"
),
x509.NameAttribute(
NameOID.COMMON_NAME,
- u'Valid pre2000 UTC notBefore Date EE Certificate Test3'
- )
+ u"Valid pre2000 UTC notBefore Date EE Certificate Test3",
+ ),
]
assert subject.get_attributes_for_oid(NameOID.COMMON_NAME) == [
x509.NameAttribute(
NameOID.COMMON_NAME,
- u'Valid pre2000 UTC notBefore Date EE Certificate Test3'
+ u"Valid pre2000 UTC notBefore Date EE Certificate Test3",
)
]
def test_unicode_name(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom",
- "utf8_common_name.pem"
- ),
+ os.path.join("x509", "custom", "utf8_common_name.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME) == [
- x509.NameAttribute(
- NameOID.COMMON_NAME,
- u'We heart UTF8!\u2122'
- )
+ x509.NameAttribute(NameOID.COMMON_NAME, u"We heart UTF8!\u2122")
]
assert cert.issuer.get_attributes_for_oid(NameOID.COMMON_NAME) == [
- x509.NameAttribute(
- NameOID.COMMON_NAME,
- u'We heart UTF8!\u2122'
- )
+ x509.NameAttribute(NameOID.COMMON_NAME, u"We heart UTF8!\u2122")
]
def test_non_ascii_dns_name(self, backend):
cert = _load_cert(
os.path.join("x509", "utf8-dnsname.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
san = cert.extensions.get_extension_for_class(
x509.SubjectAlternativeName
@@ -828,64 +906,65 @@ class TestRSACertificate(object):
names = san.get_values_for_type(x509.DNSName)
assert names == [
- u'partner.biztositas.hu', u'biztositas.hu', u'*.biztositas.hu',
- u'biztos\xedt\xe1s.hu', u'*.biztos\xedt\xe1s.hu',
- u'xn--biztosts-fza2j.hu', u'*.xn--biztosts-fza2j.hu'
+ u"partner.biztositas.hu",
+ u"biztositas.hu",
+ u"*.biztositas.hu",
+ u"biztos\xedt\xe1s.hu",
+ u"*.biztos\xedt\xe1s.hu",
+ u"xn--biztosts-fza2j.hu",
+ u"*.xn--biztosts-fza2j.hu",
]
def test_all_subject_name_types(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom",
- "all_supported_names.pem"
- ),
+ os.path.join("x509", "custom", "all_supported_names.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
subject = cert.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'AU'),
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'DE'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'California'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'New York'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'San Francisco'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Ithaca'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Org Zero, LLC'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Org One, LLC'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'CN 0'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'CN 1'),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"AU"),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"DE"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"New York"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Ithaca"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org Zero, LLC"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org One, LLC"),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"CN 0"),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"CN 1"),
x509.NameAttribute(
- NameOID.ORGANIZATIONAL_UNIT_NAME, u'Engineering 0'
+ NameOID.ORGANIZATIONAL_UNIT_NAME, u"Engineering 0"
),
x509.NameAttribute(
- NameOID.ORGANIZATIONAL_UNIT_NAME, u'Engineering 1'
+ NameOID.ORGANIZATIONAL_UNIT_NAME, u"Engineering 1"
),
- x509.NameAttribute(NameOID.DN_QUALIFIER, u'qualified0'),
- x509.NameAttribute(NameOID.DN_QUALIFIER, u'qualified1'),
- x509.NameAttribute(NameOID.SERIAL_NUMBER, u'789'),
- x509.NameAttribute(NameOID.SERIAL_NUMBER, u'012'),
- x509.NameAttribute(NameOID.TITLE, u'Title IX'),
- x509.NameAttribute(NameOID.TITLE, u'Title X'),
- x509.NameAttribute(NameOID.SURNAME, u'Last 0'),
- x509.NameAttribute(NameOID.SURNAME, u'Last 1'),
- x509.NameAttribute(NameOID.GIVEN_NAME, u'First 0'),
- x509.NameAttribute(NameOID.GIVEN_NAME, u'First 1'),
- x509.NameAttribute(NameOID.PSEUDONYM, u'Guy Incognito 0'),
- x509.NameAttribute(NameOID.PSEUDONYM, u'Guy Incognito 1'),
- x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u'32X'),
- x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u'Dreamcast'),
- x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u'dc2'),
- x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u'dc3'),
- x509.NameAttribute(NameOID.EMAIL_ADDRESS, u'test2@test.local'),
- x509.NameAttribute(NameOID.EMAIL_ADDRESS, u'test3@test.local'),
+ x509.NameAttribute(NameOID.DN_QUALIFIER, u"qualified0"),
+ x509.NameAttribute(NameOID.DN_QUALIFIER, u"qualified1"),
+ x509.NameAttribute(NameOID.SERIAL_NUMBER, u"789"),
+ x509.NameAttribute(NameOID.SERIAL_NUMBER, u"012"),
+ x509.NameAttribute(NameOID.TITLE, u"Title IX"),
+ x509.NameAttribute(NameOID.TITLE, u"Title X"),
+ x509.NameAttribute(NameOID.SURNAME, u"Last 0"),
+ x509.NameAttribute(NameOID.SURNAME, u"Last 1"),
+ x509.NameAttribute(NameOID.GIVEN_NAME, u"First 0"),
+ x509.NameAttribute(NameOID.GIVEN_NAME, u"First 1"),
+ x509.NameAttribute(NameOID.PSEUDONYM, u"Guy Incognito 0"),
+ x509.NameAttribute(NameOID.PSEUDONYM, u"Guy Incognito 1"),
+ x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"32X"),
+ x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"Dreamcast"),
+ x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc2"),
+ x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc3"),
+ x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test2@test.local"),
+ x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test3@test.local"),
]
def test_load_good_ca_cert(self, backend):
cert = _load_cert(
os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
@@ -900,11 +979,13 @@ class TestRSACertificate(object):
def test_utc_pre_2000_not_before_cert(self, backend):
cert = _load_cert(
os.path.join(
- "x509", "PKITS_data", "certs",
- "Validpre2000UTCnotBeforeDateTest3EE.crt"
+ "x509",
+ "PKITS_data",
+ "certs",
+ "Validpre2000UTCnotBeforeDateTest3EE.crt",
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
assert cert.not_valid_before == datetime.datetime(1950, 1, 1, 12, 1)
@@ -912,11 +993,13 @@ class TestRSACertificate(object):
def test_pre_2000_utc_not_after_cert(self, backend):
cert = _load_cert(
os.path.join(
- "x509", "PKITS_data", "certs",
- "Invalidpre2000UTCEEnotAfterDateTest7EE.crt"
+ "x509",
+ "PKITS_data",
+ "certs",
+ "Invalidpre2000UTCEEnotAfterDateTest7EE.crt",
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
assert cert.not_valid_after == datetime.datetime(1999, 1, 1, 12, 1)
@@ -925,7 +1008,7 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert.not_valid_before == datetime.datetime(
2014, 11, 26, 21, 41, 20
@@ -937,11 +1020,13 @@ class TestRSACertificate(object):
def test_generalized_time_not_before_cert(self, backend):
cert = _load_cert(
os.path.join(
- "x509", "PKITS_data", "certs",
- "ValidGeneralizedTimenotBeforeDateTest4EE.crt"
+ "x509",
+ "PKITS_data",
+ "certs",
+ "ValidGeneralizedTimenotBeforeDateTest4EE.crt",
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
assert cert.not_valid_before == datetime.datetime(2002, 1, 1, 12, 1)
assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30)
@@ -950,24 +1035,25 @@ class TestRSACertificate(object):
def test_generalized_time_not_after_cert(self, backend):
cert = _load_cert(
os.path.join(
- "x509", "PKITS_data", "certs",
- "ValidGeneralizedTimenotAfterDateTest8EE.crt"
+ "x509",
+ "PKITS_data",
+ "certs",
+ "ValidGeneralizedTimenotAfterDateTest8EE.crt",
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
assert cert.not_valid_after == datetime.datetime(2050, 1, 1, 12, 1)
assert cert.version is x509.Version.v3
def test_invalid_version_cert(self, backend):
- cert = _load_cert(
- os.path.join("x509", "custom", "invalid_version.pem"),
- x509.load_pem_x509_certificate,
- backend
- )
with pytest.raises(x509.InvalidVersion) as exc:
- cert.version
+ _load_cert(
+ os.path.join("x509", "custom", "invalid_version.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
assert exc.value.parsed_version == 7
@@ -975,12 +1061,12 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cert2 = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert == cert2
@@ -988,15 +1074,17 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cert2 = _load_cert(
os.path.join(
- "x509", "PKITS_data", "certs",
- "ValidGeneralizedTimenotAfterDateTest8EE.crt"
+ "x509",
+ "PKITS_data",
+ "certs",
+ "ValidGeneralizedTimenotAfterDateTest8EE.crt",
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
assert cert != cert2
assert cert != object()
@@ -1005,20 +1093,22 @@ class TestRSACertificate(object):
cert1 = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cert2 = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cert3 = _load_cert(
os.path.join(
- "x509", "PKITS_data", "certs",
- "ValidGeneralizedTimenotAfterDateTest8EE.crt"
+ "x509",
+ "PKITS_data",
+ "certs",
+ "ValidGeneralizedTimenotAfterDateTest8EE.crt",
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
assert hash(cert1) == hash(cert2)
@@ -1028,7 +1118,7 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "v1_cert.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert.version is x509.Version.v1
@@ -1044,7 +1134,7 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "verisign_md2_root.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
with pytest.raises(UnsupportedAlgorithm):
cert.signature_hash_algorithm
@@ -1054,13 +1144,16 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
# Encode it to PEM and load it back.
- cert = x509.load_pem_x509_certificate(cert.public_bytes(
- encoding=serialization.Encoding.PEM,
- ), backend)
+ cert = x509.load_pem_x509_certificate(
+ cert.public_bytes(
+ encoding=serialization.Encoding.PEM,
+ ),
+ backend,
+ )
# We should recover what we had to start with.
assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
@@ -1077,13 +1170,16 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
# Encode it to DER and load it back.
- cert = x509.load_der_x509_certificate(cert.public_bytes(
- encoding=serialization.Encoding.DER,
- ), backend)
+ cert = x509.load_der_x509_certificate(
+ cert.public_bytes(
+ encoding=serialization.Encoding.DER,
+ ),
+ backend,
+ )
# We should recover what we had to start with.
assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
@@ -1099,11 +1195,11 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
with pytest.raises(TypeError):
- cert.public_bytes('NotAnEncoding')
+ cert.public_bytes("NotAnEncoding")
@pytest.mark.parametrize(
("cert_path", "loader_func", "encoding"),
@@ -1118,10 +1214,11 @@ class TestRSACertificate(object):
x509.load_der_x509_certificate,
serialization.Encoding.DER,
),
- ]
+ ],
)
- def test_public_bytes_match(self, cert_path, loader_func, encoding,
- backend):
+ def test_public_bytes_match(
+ self, cert_path, loader_func, encoding, backend
+ ):
cert_bytes = load_vectors_from_file(
cert_path, lambda pemfile: pemfile.read(), mode="rb"
)
@@ -1131,11 +1228,9 @@ class TestRSACertificate(object):
def test_certificate_repr(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "cryptography.io.pem"
- ),
+ os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert repr(cert) == (
"<Certificate(subject=<Name(OU=GT48742965,OU=See www.rapidssl.com"
@@ -1147,7 +1242,7 @@ class TestRSACertificate(object):
cert = _load_cert(
os.path.join("x509", "tls-feature-ocsp-staple.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_class(x509.TLSFeature)
assert ext.critical is False
@@ -1164,39 +1259,99 @@ class TestRSACertificateRequest(object):
[
[
os.path.join("x509", "requests", "rsa_sha1.pem"),
- x509.load_pem_x509_csr
+ x509.load_pem_x509_csr,
],
[
os.path.join("x509", "requests", "rsa_sha1.der"),
- x509.load_der_x509_csr
+ x509.load_der_x509_csr,
],
- ]
+ ],
)
def test_load_rsa_certificate_request(self, path, loader_func, backend):
request = _load_cert(path, loader_func, backend)
assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
assert (
- request.signature_algorithm_oid ==
- SignatureAlgorithmOID.RSA_WITH_SHA1
+ request.signature_algorithm_oid
+ == SignatureAlgorithmOID.RSA_WITH_SHA1
)
public_key = request.public_key()
assert isinstance(public_key, rsa.RSAPublicKey)
subject = request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
]
extensions = request.extensions
assert isinstance(extensions, x509.Extensions)
assert list(extensions) == []
+ def test_get_attribute_for_oid_challenge(self, backend):
+ request = _load_cert(
+ os.path.join("x509", "requests", "challenge.pem"),
+ x509.load_pem_x509_csr,
+ backend,
+ )
+ assert (
+ request.get_attribute_for_oid(
+ x509.oid.AttributeOID.CHALLENGE_PASSWORD
+ )
+ == b"challenge me!"
+ )
+
+ def test_get_attribute_for_oid_multiple(self, backend):
+ request = _load_cert(
+ os.path.join("x509", "requests", "challenge-unstructured.pem"),
+ x509.load_pem_x509_csr,
+ backend,
+ )
+ assert (
+ request.get_attribute_for_oid(
+ x509.oid.AttributeOID.CHALLENGE_PASSWORD
+ )
+ == b"beauty"
+ )
+ assert (
+ request.get_attribute_for_oid(
+ x509.oid.AttributeOID.UNSTRUCTURED_NAME
+ )
+ == b"an unstructured field"
+ )
+
+ def test_invalid_attribute_for_oid(self, backend):
+ """
+ This test deliberately triggers a ValueError because to parse
+ CSR attributes we need to do a C cast. If we're wrong about the
+ type that would be Very Bad so this test confirms we properly explode
+ in the presence of the wrong types.
+ """
+ request = _load_cert(
+ os.path.join("x509", "requests", "challenge-invalid.der"),
+ x509.load_der_x509_csr,
+ backend,
+ )
+ with pytest.raises(ValueError):
+ request.get_attribute_for_oid(
+ x509.oid.AttributeOID.CHALLENGE_PASSWORD
+ )
+
+ def test_no_challenge_password(self, backend):
+ request = _load_cert(
+ os.path.join("x509", "requests", "rsa_sha256.pem"),
+ x509.load_pem_x509_csr,
+ backend,
+ )
+ with pytest.raises(x509.AttributeNotFound) as exc:
+ request.get_attribute_for_oid(
+ x509.oid.AttributeOID.CHALLENGE_PASSWORD
+ )
+ assert exc.value.oid == x509.oid.AttributeOID.CHALLENGE_PASSWORD
+
@pytest.mark.parametrize(
- "loader_func",
- [x509.load_pem_x509_csr, x509.load_der_x509_csr]
+ "loader_func", [x509.load_pem_x509_csr, x509.load_der_x509_csr]
)
def test_invalid_certificate_request(self, loader_func, backend):
with pytest.raises(ValueError):
@@ -1206,18 +1361,16 @@ class TestRSACertificateRequest(object):
request = _load_cert(
os.path.join("x509", "requests", "rsa_md4.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
with pytest.raises(UnsupportedAlgorithm):
request.signature_hash_algorithm
def test_duplicate_extension(self, backend):
request = _load_cert(
- os.path.join(
- "x509", "requests", "two_basic_constraints.pem"
- ),
+ os.path.join("x509", "requests", "two_basic_constraints.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
with pytest.raises(x509.DuplicateExtension) as exc:
request.extensions
@@ -1230,20 +1383,18 @@ class TestRSACertificateRequest(object):
"x509", "requests", "unsupported_extension_critical.pem"
),
x509.load_pem_x509_csr,
- backend
+ backend,
)
ext = request.extensions.get_extension_for_oid(
- x509.ObjectIdentifier('1.2.3.4')
+ x509.ObjectIdentifier("1.2.3.4")
)
assert ext.value.value == b"value"
def test_unsupported_extension(self, backend):
request = _load_cert(
- os.path.join(
- "x509", "requests", "unsupported_extension.pem"
- ),
+ os.path.join("x509", "requests", "unsupported_extension.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
extensions = request.extensions
assert len(extensions) == 1
@@ -1254,11 +1405,9 @@ class TestRSACertificateRequest(object):
def test_request_basic_constraints(self, backend):
request = _load_cert(
- os.path.join(
- "x509", "requests", "basic_constraints.pem"
- ),
+ os.path.join("x509", "requests", "basic_constraints.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
extensions = request.extensions
assert isinstance(extensions, x509.Extensions)
@@ -1289,13 +1438,16 @@ class TestRSACertificateRequest(object):
request = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
# Encode it to PEM and load it back.
- request = x509.load_pem_x509_csr(request.public_bytes(
- encoding=serialization.Encoding.PEM,
- ), backend)
+ request = x509.load_pem_x509_csr(
+ request.public_bytes(
+ encoding=serialization.Encoding.PEM,
+ ),
+ backend,
+ )
# We should recover what we had to start with.
assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
@@ -1304,11 +1456,11 @@ class TestRSACertificateRequest(object):
subject = request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
]
def test_public_bytes_der(self, backend):
@@ -1316,13 +1468,16 @@ class TestRSACertificateRequest(object):
request = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
# Encode it to DER and load it back.
- request = x509.load_der_x509_csr(request.public_bytes(
- encoding=serialization.Encoding.DER,
- ), backend)
+ request = x509.load_der_x509_csr(
+ request.public_bytes(
+ encoding=serialization.Encoding.DER,
+ ),
+ backend,
+ )
# We should recover what we had to start with.
assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
@@ -1331,18 +1486,18 @@ class TestRSACertificateRequest(object):
subject = request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
]
def test_signature(self, backend):
request = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert request.signature == binascii.unhexlify(
b"8364c86ffbbfe0bfc9a21f831256658ca8989741b80576d36f08a934603a43b1"
@@ -1359,7 +1514,7 @@ class TestRSACertificateRequest(object):
request = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert request.tbs_certrequest_bytes == binascii.unhexlify(
b"308201840201003057310b3009060355040613025553310e300c060355040813"
@@ -1380,24 +1535,24 @@ class TestRSACertificateRequest(object):
request.signature,
request.tbs_certrequest_bytes,
padding.PKCS1v15(),
- request.signature_hash_algorithm
+ request.signature_hash_algorithm,
)
def test_public_bytes_invalid_encoding(self, backend):
request = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
with pytest.raises(TypeError):
- request.public_bytes('NotAnEncoding')
+ request.public_bytes("NotAnEncoding")
def test_signature_invalid(self, backend):
request = _load_cert(
os.path.join("x509", "requests", "invalid_signature.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert not request.is_signature_valid
@@ -1405,7 +1560,7 @@ class TestRSACertificateRequest(object):
request = _load_cert(
os.path.join("x509", "requests", "rsa_sha256.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert request.is_signature_valid
@@ -1422,10 +1577,11 @@ class TestRSACertificateRequest(object):
x509.load_der_x509_csr,
serialization.Encoding.DER,
),
- ]
+ ],
)
- def test_public_bytes_match(self, request_path, loader_func, encoding,
- backend):
+ def test_public_bytes_match(
+ self, request_path, loader_func, encoding, backend
+ ):
request_bytes = load_vectors_from_file(
request_path, lambda pemfile: pemfile.read(), mode="rb"
)
@@ -1437,12 +1593,12 @@ class TestRSACertificateRequest(object):
request1 = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
request2 = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert request1 == request2
@@ -1451,12 +1607,12 @@ class TestRSACertificateRequest(object):
request1 = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
request2 = _load_cert(
os.path.join("x509", "requests", "san_rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert request1 != request2
@@ -1466,17 +1622,17 @@ class TestRSACertificateRequest(object):
request1 = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
request2 = _load_cert(
os.path.join("x509", "requests", "rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
request3 = _load_cert(
os.path.join("x509", "requests", "san_rsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert hash(request1) == hash(request2)
@@ -1489,31 +1645,52 @@ class TestRSACertificateRequest(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
- ])).public_key(
- subject_private_key.public_key()
- ).add_extension(
- x509.BasicConstraints(ca=False, path_length=None), True,
- ).add_extension(
- x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
- critical=False,
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+ ),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io"
+ ),
+ ]
+ )
+ )
+ .subject_name(
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+ ),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io"
+ ),
+ ]
+ )
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(
+ x509.BasicConstraints(ca=False, path_length=None),
+ True,
+ )
+ .add_extension(
+ x509.SubjectAlternativeName(
+ [x509.DNSName(u"cryptography.io")]
+ ),
+ critical=False,
+ )
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
@@ -1538,37 +1715,49 @@ class TestRSACertificateRequest(object):
subject_private_key = RSA_KEY_2048.private_key(backend)
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- name = x509.Name([
- x509.NameAttribute(
- NameOID.STATE_OR_PROVINCE_NAME, u'Texas',
- _ASN1Type.PrintableString),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
- x509.NameAttribute(
- NameOID.COMMON_NAME, u'cryptography.io', _ASN1Type.IA5String),
- ])
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(
- name
- ).subject_name(
- name
- ).public_key(
- subject_private_key.public_key()
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(not_valid_after)
+ name = x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME,
+ u"Texas",
+ _ASN1Type.PrintableString,
+ ),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"cryptography.io",
+ _ASN1Type.IA5String,
+ ),
+ ]
+ )
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(name)
+ .subject_name(name)
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
+ )
cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
for dn in (cert.subject, cert.issuer):
- assert dn.get_attributes_for_oid(
- NameOID.STATE_OR_PROVINCE_NAME
- )[0]._type == _ASN1Type.PrintableString
- assert dn.get_attributes_for_oid(
- NameOID.STATE_OR_PROVINCE_NAME
- )[0]._type == _ASN1Type.PrintableString
- assert dn.get_attributes_for_oid(
- NameOID.LOCALITY_NAME
- )[0]._type == _ASN1Type.UTF8String
+ assert (
+ dn.get_attributes_for_oid(NameOID.STATE_OR_PROVINCE_NAME)[
+ 0
+ ]._type
+ == _ASN1Type.PrintableString
+ )
+ assert (
+ dn.get_attributes_for_oid(NameOID.STATE_OR_PROVINCE_NAME)[
+ 0
+ ]._type
+ == _ASN1Type.PrintableString
+ )
+ assert (
+ dn.get_attributes_for_oid(NameOID.LOCALITY_NAME)[0]._type
+ == _ASN1Type.UTF8String
+ )
def test_build_cert_printable_string_country_name(self, backend):
issuer_private_key = RSA_KEY_2048.private_key(backend)
@@ -1577,41 +1766,65 @@ class TestRSACertificateRequest(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- ])).public_key(
- subject_private_key.public_key()
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(
+ NameOID.JURISDICTION_COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+ ),
+ ]
+ )
+ )
+ .subject_name(
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(
+ NameOID.JURISDICTION_COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+ ),
+ ]
+ )
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
- parsed = Certificate.load(
- cert.public_bytes(serialization.Encoding.DER))
+ parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER))
+ subject = parsed.subject
+ issuer = parsed.issuer
+
+ def read_next_rdn_value_tag(reader):
+ # Assume each RDN has a single attribute.
+ with reader.read_element(SET) as rdn:
+ attribute = rdn.read_element(SEQUENCE)
+
+ with attribute:
+ _ = attribute.read_element(OBJECT_IDENTIFIER)
+ tag, value = attribute.read_any_element()
+ return tag
# Check that each value was encoded as an ASN.1 PRINTABLESTRING.
- assert parsed.subject.chosen[0][0]['value'].chosen.tag == 19
- assert parsed.issuer.chosen[0][0]['value'].chosen.tag == 19
+ assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING
+ assert read_next_rdn_value_tag(issuer) == PRINTABLE_STRING
if (
# This only works correctly in OpenSSL 1.1.0f+ and 1.0.2l+
- backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER or (
- backend._lib.CRYPTOGRAPHY_OPENSSL_102L_OR_GREATER and
- not backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER
- )
+ backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER
):
- assert parsed.subject.chosen[1][0]['value'].chosen.tag == 19
- assert parsed.issuer.chosen[1][0]['value'].chosen.tag == 19
+ assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING
+ assert read_next_rdn_value_tag(issuer) == PRINTABLE_STRING
class TestCertificateBuilder(object):
@@ -1619,20 +1832,19 @@ class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_checks_for_unsupported_extensions(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- private_key.public_key()
- ).serial_number(
- 777
- ).not_valid_before(
- datetime.datetime(1999, 1, 1)
- ).not_valid_after(
- datetime.datetime(2020, 1, 1)
- ).add_extension(
- DummyExtension(), False
+ builder = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(private_key.public_key())
+ .serial_number(777)
+ .not_valid_before(datetime.datetime(1999, 1, 1))
+ .not_valid_after(datetime.datetime(2020, 1, 1))
+ .add_extension(DummyExtension(), False)
)
with pytest.raises(NotImplementedError):
@@ -1643,133 +1855,163 @@ class TestCertificateBuilder(object):
def test_encode_nonstandard_aia(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- aia = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- x509.ObjectIdentifier("2.999.7"),
- x509.UniformResourceIdentifier(u"http://example.com")
- ),
- ])
-
- builder = x509.CertificateBuilder().subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- private_key.public_key()
- ).serial_number(
- 777
- ).not_valid_before(
- datetime.datetime(1999, 1, 1)
- ).not_valid_after(
- datetime.datetime(2020, 1, 1)
- ).add_extension(
- aia, False
+ aia = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ x509.ObjectIdentifier("2.999.7"),
+ x509.UniformResourceIdentifier(u"http://example.com"),
+ ),
+ ]
+ )
+
+ builder = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(private_key.public_key())
+ .serial_number(777)
+ .not_valid_before(datetime.datetime(1999, 1, 1))
+ .not_valid_after(datetime.datetime(2020, 1, 1))
+ .add_extension(aia, False)
)
builder.sign(private_key, hashes.SHA256(), backend)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_encode_nonstandard_sia(self, backend):
+ private_key = RSA_KEY_2048.private_key(backend)
+
+ sia = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ x509.ObjectIdentifier("2.999.7"),
+ x509.UniformResourceIdentifier(u"http://example.com"),
+ ),
+ ]
+ )
+
+ builder = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(private_key.public_key())
+ .serial_number(777)
+ .not_valid_before(datetime.datetime(2015, 1, 1))
+ .not_valid_after(datetime.datetime(2040, 1, 1))
+ .add_extension(sia, False)
+ )
+
+ cert = builder.sign(private_key, hashes.SHA256(), backend)
+ ext = cert.extensions.get_extension_for_oid(
+ ExtensionOID.SUBJECT_INFORMATION_ACCESS
+ )
+ assert ext.value == sia
+
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
def test_subject_dn_asn1_types(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- name = x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u"value"),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"value"),
- x509.NameAttribute(NameOID.STREET_ADDRESS, u"value"),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"value"),
- x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"value"),
- x509.NameAttribute(NameOID.SERIAL_NUMBER, u"value"),
- x509.NameAttribute(NameOID.SURNAME, u"value"),
- x509.NameAttribute(NameOID.GIVEN_NAME, u"value"),
- x509.NameAttribute(NameOID.TITLE, u"value"),
- x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"value"),
- x509.NameAttribute(NameOID.X500_UNIQUE_IDENTIFIER, u"value"),
- x509.NameAttribute(NameOID.DN_QUALIFIER, u"value"),
- x509.NameAttribute(NameOID.PSEUDONYM, u"value"),
- x509.NameAttribute(NameOID.USER_ID, u"value"),
- x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"value"),
- x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"value"),
- x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, u"US"),
- x509.NameAttribute(NameOID.JURISDICTION_LOCALITY_NAME, u"value"),
- x509.NameAttribute(
- NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, u"value"
- ),
- x509.NameAttribute(NameOID.BUSINESS_CATEGORY, u"value"),
- x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
- x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
- ])
- cert = x509.CertificateBuilder().subject_name(
- name
- ).issuer_name(
- name
- ).public_key(
- private_key.public_key()
- ).serial_number(
- 777
- ).not_valid_before(
- datetime.datetime(1999, 1, 1)
- ).not_valid_after(
- datetime.datetime(2020, 1, 1)
- ).sign(private_key, hashes.SHA256(), backend)
+ name = x509.Name(
+ [
+ x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"value"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"value"),
+ x509.NameAttribute(NameOID.STREET_ADDRESS, u"value"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"value"),
+ x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"value"),
+ x509.NameAttribute(NameOID.SERIAL_NUMBER, u"value"),
+ x509.NameAttribute(NameOID.SURNAME, u"value"),
+ x509.NameAttribute(NameOID.GIVEN_NAME, u"value"),
+ x509.NameAttribute(NameOID.TITLE, u"value"),
+ x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"value"),
+ x509.NameAttribute(NameOID.X500_UNIQUE_IDENTIFIER, u"value"),
+ x509.NameAttribute(NameOID.DN_QUALIFIER, u"value"),
+ x509.NameAttribute(NameOID.PSEUDONYM, u"value"),
+ x509.NameAttribute(NameOID.USER_ID, u"value"),
+ x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"value"),
+ x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"value"),
+ x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, u"US"),
+ x509.NameAttribute(
+ NameOID.JURISDICTION_LOCALITY_NAME, u"value"
+ ),
+ x509.NameAttribute(
+ NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, u"value"
+ ),
+ x509.NameAttribute(NameOID.BUSINESS_CATEGORY, u"value"),
+ x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
+ x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
+ ]
+ )
+ cert = (
+ x509.CertificateBuilder()
+ .subject_name(name)
+ .issuer_name(name)
+ .public_key(private_key.public_key())
+ .serial_number(777)
+ .not_valid_before(datetime.datetime(1999, 1, 1))
+ .not_valid_after(datetime.datetime(2020, 1, 1))
+ .sign(private_key, hashes.SHA256(), backend)
+ )
for dn in (cert.subject, cert.issuer):
for oid, asn1_type in TestNameAttribute.EXPECTED_TYPES:
- assert dn.get_attributes_for_oid(
- oid
- )[0]._type == asn1_type
+ assert dn.get_attributes_for_oid(oid)[0]._type == asn1_type
@pytest.mark.parametrize(
("not_valid_before", "not_valid_after"),
[
[datetime.datetime(1970, 2, 1), datetime.datetime(9999, 1, 1)],
[datetime.datetime(1970, 2, 1), datetime.datetime(9999, 12, 31)],
- ]
+ ],
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_extreme_times(self, not_valid_before, not_valid_after, backend):
private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- private_key.public_key()
- ).serial_number(
- 777
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ builder = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(private_key.public_key())
+ .serial_number(777)
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
cert = builder.sign(private_key, hashes.SHA256(), backend)
assert cert.not_valid_before == not_valid_before
assert cert.not_valid_after == not_valid_after
- parsed = Certificate.load(
- cert.public_bytes(serialization.Encoding.DER)
- )
- not_before = parsed['tbs_certificate']['validity']['not_before']
- not_after = parsed['tbs_certificate']['validity']['not_after']
- assert not_before.chosen.tag == 23 # UTCTime
- assert not_after.chosen.tag == 24 # GeneralizedTime
+ parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER))
+ assert parsed.not_before_tag == UTC_TIME
+ assert parsed.not_after_tag == GENERALIZED_TIME
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_no_subject_name(self, backend):
subject_private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2030, 12, 31, 8, 30)
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
)
with pytest.raises(ValueError):
builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1778,16 +2020,15 @@ class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_no_issuer_name(self, backend):
subject_private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2030, 12, 31, 8, 30)
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
)
with pytest.raises(ValueError):
builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1796,16 +2037,17 @@ class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_no_public_key(self, backend):
subject_private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2030, 12, 31, 8, 30)
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
)
with pytest.raises(ValueError):
builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1814,16 +2056,17 @@ class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_no_not_valid_before(self, backend):
subject_private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).not_valid_after(
- datetime.datetime(2030, 12, 31, 8, 30)
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
)
with pytest.raises(ValueError):
builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1832,16 +2075,17 @@ class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_no_not_valid_after(self, backend):
subject_private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
)
with pytest.raises(ValueError):
builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1850,16 +2094,17 @@ class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_no_serial_number(self, backend):
subject_private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2030, 12, 31, 8, 30)
+ builder = (
+ x509.CertificateBuilder()
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
)
with pytest.raises(ValueError):
builder.sign(subject_private_key, hashes.SHA256(), backend)
@@ -1874,9 +2119,7 @@ class TestCertificateBuilder(object):
builder.issuer_name(object)
def test_issuer_name_may_only_be_set_once(self):
- name = x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])
+ name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
builder = x509.CertificateBuilder().issuer_name(name)
with pytest.raises(ValueError):
@@ -1892,9 +2135,7 @@ class TestCertificateBuilder(object):
builder.subject_name(object)
def test_subject_name_may_only_be_set_once(self):
- name = x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])
+ name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
builder = x509.CertificateBuilder().subject_name(name)
with pytest.raises(ValueError):
@@ -1903,13 +2144,9 @@ class TestCertificateBuilder(object):
def test_not_valid_before_after_not_valid_after(self):
builder = x509.CertificateBuilder()
- builder = builder.not_valid_after(
- datetime.datetime(2002, 1, 1, 12, 1)
- )
+ builder = builder.not_valid_after(datetime.datetime(2002, 1, 1, 12, 1))
with pytest.raises(ValueError):
- builder.not_valid_before(
- datetime.datetime(2003, 1, 1, 12, 1)
- )
+ builder.not_valid_before(datetime.datetime(2003, 1, 1, 12, 1))
def test_not_valid_after_before_not_valid_before(self):
builder = x509.CertificateBuilder()
@@ -1918,9 +2155,7 @@ class TestCertificateBuilder(object):
datetime.datetime(2002, 1, 1, 12, 1)
)
with pytest.raises(ValueError):
- builder.not_valid_after(
- datetime.datetime(2001, 1, 1, 12, 1)
- )
+ builder.not_valid_after(datetime.datetime(2001, 1, 1, 12, 1))
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
@@ -1957,18 +2192,18 @@ class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_minimal_serial_number(self, backend):
subject_private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().serial_number(
- 1
- ).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'RU'),
- ])).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'RU'),
- ])).public_key(
- subject_private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2030, 12, 31, 8, 30)
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(1)
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
)
cert = builder.sign(subject_private_key, hashes.SHA256(), backend)
assert cert.serial_number == 1
@@ -1977,18 +2212,18 @@ class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_biggest_serial_number(self, backend):
subject_private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateBuilder().serial_number(
- (1 << 159) - 1
- ).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'RU'),
- ])).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'RU'),
- ])).public_key(
- subject_private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2030, 12, 31, 8, 30)
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number((1 << 159) - 1)
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
)
cert = builder.sign(subject_private_key, hashes.SHA256(), backend)
assert cert.serial_number == (1 << 159) - 1
@@ -2012,16 +2247,16 @@ class TestCertificateBuilder(object):
utc_time = datetime.datetime(2012, 1, 17, 6, 43)
private_key = RSA_KEY_2048.private_key(backend)
cert_builder = x509.CertificateBuilder().not_valid_after(time)
- cert_builder = cert_builder.subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).serial_number(
- 1
- ).public_key(
- private_key.public_key()
- ).not_valid_before(
- utc_time - datetime.timedelta(days=365)
+ cert_builder = (
+ cert_builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .serial_number(1)
+ .public_key(private_key.public_key())
+ .not_valid_before(utc_time - datetime.timedelta(days=365))
)
cert = cert_builder.sign(private_key, hashes.SHA256(), backend)
@@ -2032,29 +2267,25 @@ class TestCertificateBuilder(object):
def test_earliest_time(self, backend):
time = datetime.datetime(1950, 1, 1)
private_key = RSA_KEY_2048.private_key(backend)
- cert_builder = x509.CertificateBuilder().subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).serial_number(
- 1
- ).public_key(
- private_key.public_key()
- ).not_valid_before(
- time
- ).not_valid_after(
- time
+ cert_builder = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .serial_number(1)
+ .public_key(private_key.public_key())
+ .not_valid_before(time)
+ .not_valid_after(time)
)
cert = cert_builder.sign(private_key, hashes.SHA256(), backend)
assert cert.not_valid_before == time
assert cert.not_valid_after == time
- parsed = Certificate.load(
- cert.public_bytes(serialization.Encoding.DER)
- )
- not_before = parsed['tbs_certificate']['validity']['not_before']
- not_after = parsed['tbs_certificate']['validity']['not_after']
- assert not_before.chosen.tag == 23 # UTCTime
- assert not_after.chosen.tag == 23 # UTCTime
+ parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER))
+ assert parsed.not_before_tag == UTC_TIME
+ assert parsed.not_after_tag == UTC_TIME
def test_invalid_not_valid_after(self):
with pytest.raises(TypeError):
@@ -2074,9 +2305,7 @@ class TestCertificateBuilder(object):
)
with pytest.raises(ValueError):
- builder.not_valid_after(
- datetime.datetime.now()
- )
+ builder.not_valid_after(datetime.datetime.now())
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
@@ -2087,16 +2316,16 @@ class TestCertificateBuilder(object):
utc_time = datetime.datetime(2012, 1, 17, 6, 43)
private_key = RSA_KEY_2048.private_key(backend)
cert_builder = x509.CertificateBuilder().not_valid_before(time)
- cert_builder = cert_builder.subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).serial_number(
- 1
- ).public_key(
- private_key.public_key()
- ).not_valid_after(
- utc_time + datetime.timedelta(days=366)
+ cert_builder = (
+ cert_builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .serial_number(1)
+ .public_key(private_key.public_key())
+ .not_valid_after(utc_time + datetime.timedelta(days=366))
)
cert = cert_builder.sign(private_key, hashes.SHA256(), backend)
@@ -2120,18 +2349,18 @@ class TestCertificateBuilder(object):
)
with pytest.raises(ValueError):
- builder.not_valid_before(
- datetime.datetime.now()
- )
+ builder.not_valid_before(datetime.datetime.now())
def test_add_extension_checks_for_duplicates(self):
builder = x509.CertificateBuilder().add_extension(
- x509.BasicConstraints(ca=False, path_length=None), True,
+ x509.BasicConstraints(ca=False, path_length=None),
+ True,
)
with pytest.raises(ValueError):
builder.add_extension(
- x509.BasicConstraints(ca=False, path_length=None), True,
+ x509.BasicConstraints(ca=False, path_length=None),
+ True,
)
def test_add_invalid_extension_type(self):
@@ -2142,86 +2371,143 @@ class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
- def test_sign_with_unsupported_hash(self, backend):
+ @pytest.mark.parametrize("algorithm", [object(), None])
+ def test_sign_with_unsupported_hash(self, algorithm, backend):
private_key = RSA_KEY_2048.private_key(backend)
builder = x509.CertificateBuilder()
- builder = builder.subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).serial_number(
- 1
- ).public_key(
- private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2032, 1, 1, 12, 1)
+ builder = (
+ builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .serial_number(1)
+ .public_key(private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
)
with pytest.raises(TypeError):
- builder.sign(private_key, object(), backend)
+ builder.sign(private_key, algorithm, backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_sign_with_unsupported_hash_ed25519(self, backend):
+ private_key = ed25519.Ed25519PrivateKey.generate()
+ builder = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .serial_number(1)
+ .public_key(private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
+ )
+
+ with pytest.raises(ValueError):
+ builder.sign(private_key, hashes.SHA256(), backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_sign_with_unsupported_hash_ed448(self, backend):
+ private_key = ed448.Ed448PrivateKey.generate()
+ builder = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .serial_number(1)
+ .public_key(private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
+ )
+
+ with pytest.raises(ValueError):
+ builder.sign(private_key, hashes.SHA256(), backend)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.hash_supported(hashes.MD5()),
+ skip_message="Requires OpenSSL with MD5 support",
+ )
def test_sign_rsa_with_md5(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
builder = x509.CertificateBuilder()
- builder = builder.subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).serial_number(
- 1
- ).public_key(
- private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2032, 1, 1, 12, 1)
+ builder = (
+ builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .serial_number(1)
+ .public_key(private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
)
cert = builder.sign(private_key, hashes.MD5(), backend)
assert isinstance(cert.signature_hash_algorithm, hashes.MD5)
@pytest.mark.requires_backend_interface(interface=DSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.hash_supported(hashes.MD5()),
+ skip_message="Requires OpenSSL with MD5 support",
+ )
def test_sign_dsa_with_md5(self, backend):
private_key = DSA_KEY_2048.private_key(backend)
builder = x509.CertificateBuilder()
- builder = builder.subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).serial_number(
- 1
- ).public_key(
- private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2032, 1, 1, 12, 1)
+ builder = (
+ builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .serial_number(1)
+ .public_key(private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
)
with pytest.raises(ValueError):
builder.sign(private_key, hashes.MD5(), backend)
@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.hash_supported(hashes.MD5()),
+ skip_message="Requires OpenSSL with MD5 support",
+ )
def test_sign_ec_with_md5(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
private_key = EC_KEY_SECP256R1.private_key(backend)
builder = x509.CertificateBuilder()
- builder = builder.subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).serial_number(
- 1
- ).public_key(
- private_key.public_key()
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2032, 1, 1, 12, 1)
+ builder = (
+ builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .serial_number(1)
+ .public_key(private_key.public_key())
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
)
with pytest.raises(ValueError):
builder.sign(private_key, hashes.MD5(), backend)
@@ -2235,23 +2521,28 @@ class TestCertificateBuilder(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).add_extension(
- x509.BasicConstraints(ca=False, path_length=None), True,
- ).add_extension(
- x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
- critical=False,
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(
+ x509.BasicConstraints(ca=False, path_length=None),
+ True,
+ )
+ .add_extension(
+ x509.SubjectAlternativeName(
+ [x509.DNSName(u"cryptography.io")]
+ ),
+ critical=False,
+ )
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
@@ -2281,23 +2572,28 @@ class TestCertificateBuilder(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).add_extension(
- x509.BasicConstraints(ca=False, path_length=None), True,
- ).add_extension(
- x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
- critical=False,
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(
+ x509.BasicConstraints(ca=False, path_length=None),
+ True,
+ )
+ .add_extension(
+ x509.SubjectAlternativeName(
+ [x509.DNSName(u"cryptography.io")]
+ ),
+ critical=False,
+ )
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
@@ -2317,6 +2613,202 @@ class TestCertificateBuilder(object):
x509.DNSName(u"cryptography.io"),
]
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_build_cert_with_ed25519(self, backend):
+ issuer_private_key = ed25519.Ed25519PrivateKey.generate()
+ subject_private_key = ed25519.Ed25519PrivateKey.generate()
+
+ not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+ not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(
+ x509.BasicConstraints(ca=False, path_length=None),
+ True,
+ )
+ .add_extension(
+ x509.SubjectAlternativeName(
+ [x509.DNSName(u"cryptography.io")]
+ ),
+ critical=False,
+ )
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
+ )
+
+ cert = builder.sign(issuer_private_key, None, backend)
+ issuer_private_key.public_key().verify(
+ cert.signature, cert.tbs_certificate_bytes
+ )
+ assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED25519
+ assert cert.signature_hash_algorithm is None
+ assert isinstance(cert.public_key(), ed25519.Ed25519PublicKey)
+ assert cert.version is x509.Version.v3
+ assert cert.not_valid_before == not_valid_before
+ assert cert.not_valid_after == not_valid_after
+ basic_constraints = cert.extensions.get_extension_for_oid(
+ ExtensionOID.BASIC_CONSTRAINTS
+ )
+ assert basic_constraints.value.ca is False
+ assert basic_constraints.value.path_length is None
+ subject_alternative_name = cert.extensions.get_extension_for_oid(
+ ExtensionOID.SUBJECT_ALTERNATIVE_NAME
+ )
+ assert list(subject_alternative_name.value) == [
+ x509.DNSName(u"cryptography.io"),
+ ]
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ def test_build_cert_with_public_ed25519_rsa_sig(self, backend):
+ issuer_private_key = RSA_KEY_2048.private_key(backend)
+ subject_private_key = ed25519.Ed25519PrivateKey.generate()
+
+ not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+ not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
+ )
+
+ cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
+ issuer_private_key.public_key().verify(
+ cert.signature,
+ cert.tbs_certificate_bytes,
+ padding.PKCS1v15(),
+ cert.signature_hash_algorithm,
+ )
+ assert cert.signature_algorithm_oid == (
+ SignatureAlgorithmOID.RSA_WITH_SHA256
+ )
+ assert isinstance(cert.signature_hash_algorithm, hashes.SHA256)
+ assert isinstance(cert.public_key(), ed25519.Ed25519PublicKey)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_build_cert_with_ed448(self, backend):
+ issuer_private_key = ed448.Ed448PrivateKey.generate()
+ subject_private_key = ed448.Ed448PrivateKey.generate()
+
+ not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+ not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(
+ x509.BasicConstraints(ca=False, path_length=None),
+ True,
+ )
+ .add_extension(
+ x509.SubjectAlternativeName(
+ [x509.DNSName(u"cryptography.io")]
+ ),
+ critical=False,
+ )
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
+ )
+
+ cert = builder.sign(issuer_private_key, None, backend)
+ issuer_private_key.public_key().verify(
+ cert.signature, cert.tbs_certificate_bytes
+ )
+ assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED448
+ assert cert.signature_hash_algorithm is None
+ assert isinstance(cert.public_key(), ed448.Ed448PublicKey)
+ assert cert.version is x509.Version.v3
+ assert cert.not_valid_before == not_valid_before
+ assert cert.not_valid_after == not_valid_after
+ basic_constraints = cert.extensions.get_extension_for_oid(
+ ExtensionOID.BASIC_CONSTRAINTS
+ )
+ assert basic_constraints.value.ca is False
+ assert basic_constraints.value.path_length is None
+ subject_alternative_name = cert.extensions.get_extension_for_oid(
+ ExtensionOID.SUBJECT_ALTERNATIVE_NAME
+ )
+ assert list(subject_alternative_name.value) == [
+ x509.DNSName(u"cryptography.io"),
+ ]
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ def test_build_cert_with_public_ed448_rsa_sig(self, backend):
+ issuer_private_key = RSA_KEY_2048.private_key(backend)
+ subject_private_key = ed448.Ed448PrivateKey.generate()
+
+ not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+ not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
+ )
+
+ cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
+ issuer_private_key.public_key().verify(
+ cert.signature,
+ cert.tbs_certificate_bytes,
+ padding.PKCS1v15(),
+ cert.signature_hash_algorithm,
+ )
+ assert cert.signature_algorithm_oid == (
+ SignatureAlgorithmOID.RSA_WITH_SHA256
+ )
+ assert isinstance(cert.signature_hash_algorithm, hashes.SHA256)
+ assert isinstance(cert.public_key(), ed448.Ed448PublicKey)
+
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_build_cert_with_rsa_key_too_small(self, backend):
@@ -2326,18 +2818,18 @@ class TestCertificateBuilder(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
with pytest.raises(ValueError):
@@ -2352,85 +2844,105 @@ class TestCertificateBuilder(object):
[
# These examples exist to verify compatibility with
# certificates that have utf8 encoded data in the ia5string
- x509.DNSName._init_without_validation(u'a\xedt\xe1s.test'),
+ x509.DNSName._init_without_validation(u"a\xedt\xe1s.test"),
x509.RFC822Name._init_without_validation(
- u'test@a\xedt\xe1s.test'
+ u"test@a\xedt\xe1s.test"
),
x509.UniformResourceIdentifier._init_without_validation(
- u'http://a\xedt\xe1s.test'
+ u"http://a\xedt\xe1s.test"
),
]
),
- x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- [u"http://other.com/cps"]
- )
- ]),
- x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- None
- )
- ]),
- x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- [
- u"http://example.com/cps",
- u"http://other.com/cps",
- x509.UserNotice(
- x509.NoticeReference(u"my org", [1, 2, 3, 4]),
- u"thing"
- )
- ]
- )
- ]),
- x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- [
- u"http://example.com/cps",
- x509.UserNotice(
- x509.NoticeReference(u"UTF8\u2122'", [1, 2, 3, 4]),
- u"We heart UTF8!\u2122"
- )
- ]
- )
- ]),
- x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- [x509.UserNotice(None, u"thing")]
- )
- ]),
- x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- [
- x509.UserNotice(
- x509.NoticeReference(u"my org", [1, 2, 3, 4]),
- None
- )
- ]
- )
- ]),
- x509.IssuerAlternativeName([
- x509.DNSName(u"myissuer"),
- x509.RFC822Name(u"email@domain.com"),
- ]),
- x509.ExtendedKeyUsage([
- ExtendedKeyUsageOID.CLIENT_AUTH,
- ExtendedKeyUsageOID.SERVER_AUTH,
- ExtendedKeyUsageOID.CODE_SIGNING,
- ]),
+ x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [u"http://other.com/cps"],
+ )
+ ]
+ ),
+ x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ None,
+ )
+ ]
+ ),
+ x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ u"http://example.com/cps",
+ u"http://other.com/cps",
+ x509.UserNotice(
+ x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+ u"thing",
+ ),
+ ],
+ )
+ ]
+ ),
+ x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ u"http://example.com/cps",
+ x509.UserNotice(
+ x509.NoticeReference(
+ u"UTF8\u2122'", [1, 2, 3, 4]
+ ),
+ u"We heart UTF8!\u2122",
+ ),
+ ],
+ )
+ ]
+ ),
+ x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [x509.UserNotice(None, u"thing")],
+ )
+ ]
+ ),
+ x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ x509.UserNotice(
+ x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+ None,
+ )
+ ],
+ )
+ ]
+ ),
+ x509.IssuerAlternativeName(
+ [
+ x509.DNSName(u"myissuer"),
+ x509.RFC822Name(u"email@domain.com"),
+ ]
+ ),
+ x509.ExtendedKeyUsage(
+ [
+ ExtendedKeyUsageOID.CLIENT_AUTH,
+ ExtendedKeyUsageOID.SERVER_AUTH,
+ ExtendedKeyUsageOID.CODE_SIGNING,
+ ]
+ ),
x509.InhibitAnyPolicy(3),
x509.TLSFeature([x509.TLSFeatureType.status_request]),
x509.TLSFeature([x509.TLSFeatureType.status_request_v2]),
- x509.TLSFeature([
- x509.TLSFeatureType.status_request,
- x509.TLSFeatureType.status_request_v2
- ]),
+ x509.TLSFeature(
+ [
+ x509.TLSFeatureType.status_request,
+ x509.TLSFeatureType.status_request_v2,
+ ]
+ ),
x509.NameConstraints(
permitted_subtrees=[
x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24")),
@@ -2445,192 +2957,252 @@ class TestCertificateBuilder(object):
ipaddress.IPv6Network(u"FF:FF:0:0:0:0:0:0/128")
),
],
- excluded_subtrees=[x509.DNSName(u"name.local")]
+ excluded_subtrees=[x509.DNSName(u"name.local")],
),
x509.NameConstraints(
permitted_subtrees=[
x509.IPAddress(ipaddress.IPv4Network(u"0.0.0.0/0")),
],
- excluded_subtrees=None
+ excluded_subtrees=None,
),
x509.NameConstraints(
permitted_subtrees=None,
- excluded_subtrees=[x509.DNSName(u"name.local")]
+ excluded_subtrees=[x509.DNSName(u"name.local")],
),
x509.PolicyConstraints(
- require_explicit_policy=None,
- inhibit_policy_mapping=1
+ require_explicit_policy=None, inhibit_policy_mapping=1
),
x509.PolicyConstraints(
- require_explicit_policy=3,
- inhibit_policy_mapping=1
+ require_explicit_policy=3, inhibit_policy_mapping=1
),
x509.PolicyConstraints(
- require_explicit_policy=0,
- inhibit_policy_mapping=None
+ require_explicit_policy=0, inhibit_policy_mapping=None
),
- x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- NameOID.COMMON_NAME,
- u"indirect CRL for indirectCRL CA3"
+ x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=None,
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"indirect CRL for indirectCRL CA3",
+ ),
+ ]
),
- ]),
- reasons=None,
- crl_issuer=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME,
- u"Test Certificates 2011"
- ),
- x509.NameAttribute(
- NameOID.ORGANIZATIONAL_UNIT_NAME,
- u"indirectCRL CA3 cRLIssuer"
+ reasons=None,
+ crl_issuer=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME,
+ u"Test Certificates 2011",
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATIONAL_UNIT_NAME,
+ u"indirectCRL CA3 cRLIssuer",
+ ),
+ ]
+ )
+ )
+ ],
+ )
+ ]
+ ),
+ x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COUNTRY_NAME, u"US"
+ ),
+ ]
+ )
+ )
+ ],
+ relative_name=None,
+ reasons=None,
+ crl_issuer=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME,
+ u"cryptography Testing",
+ ),
+ ]
+ )
+ )
+ ],
+ )
+ ]
+ ),
+ x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"http://myhost.com/myca.crl"
),
- ])
- )],
- )
- ]),
- x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- ])
- )],
- relative_name=None,
- reasons=None,
- crl_issuer=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME,
- u"cryptography Testing"
+ x509.UniformResourceIdentifier(
+ u"http://backup.myhost.com/myca.crl"
),
- ])
- )],
- )
- ]),
- x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=[
- x509.UniformResourceIdentifier(
- u"http://myhost.com/myca.crl"
+ ],
+ relative_name=None,
+ reasons=frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
),
- x509.UniformResourceIdentifier(
- u"http://backup.myhost.com/myca.crl"
- )
- ],
- relative_name=None,
- reasons=frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise
- ]),
- crl_issuer=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"cryptography CA"
- ),
- ])
- )],
- )
- ]),
- x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=[x509.UniformResourceIdentifier(
- u"http://domain.com/some.crl"
- )],
- relative_name=None,
- reasons=frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- x509.ReasonFlags.affiliation_changed,
- x509.ReasonFlags.superseded,
- x509.ReasonFlags.privilege_withdrawn,
- x509.ReasonFlags.cessation_of_operation,
- x509.ReasonFlags.aa_compromise,
- x509.ReasonFlags.certificate_hold,
- ]),
- crl_issuer=None
- )
- ]),
- x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=None,
- relative_name=None,
- reasons=None,
- crl_issuer=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"cryptography CA"
- ),
- ])
- )],
- )
- ]),
- x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=[x509.UniformResourceIdentifier(
- u"http://domain.com/some.crl"
- )],
- relative_name=None,
- reasons=frozenset([x509.ReasonFlags.aa_compromise]),
- crl_issuer=None
- )
- ]),
- x509.FreshestCRL([
- x509.DistributionPoint(
- full_name=[x509.UniformResourceIdentifier(
- u"http://domain.com/some.crl"
- )],
- relative_name=None,
- reasons=frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- x509.ReasonFlags.affiliation_changed,
- x509.ReasonFlags.superseded,
- x509.ReasonFlags.privilege_withdrawn,
- x509.ReasonFlags.cessation_of_operation,
- x509.ReasonFlags.aa_compromise,
- x509.ReasonFlags.certificate_hold,
- ]),
- crl_issuer=None
- )
- ]),
- x509.FreshestCRL([
- x509.DistributionPoint(
- full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- NameOID.COMMON_NAME,
- u"indirect CRL for indirectCRL CA3"
+ crl_issuer=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"cryptography CA",
+ ),
+ ]
+ )
+ )
+ ],
+ )
+ ]
+ ),
+ x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/some.crl"
+ )
+ ],
+ relative_name=None,
+ reasons=frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ x509.ReasonFlags.affiliation_changed,
+ x509.ReasonFlags.superseded,
+ x509.ReasonFlags.privilege_withdrawn,
+ x509.ReasonFlags.cessation_of_operation,
+ x509.ReasonFlags.aa_compromise,
+ x509.ReasonFlags.certificate_hold,
+ ]
),
- ]),
- reasons=None,
- crl_issuer=None,
- )
- ]),
- x509.FreshestCRL([
- x509.DistributionPoint(
- full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- NameOID.COMMON_NAME,
- u"indirect CRL for indirectCRL CA3"
+ crl_issuer=None,
+ )
+ ]
+ ),
+ x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=None,
+ relative_name=None,
+ reasons=None,
+ crl_issuer=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"cryptography CA",
+ ),
+ ]
+ )
+ )
+ ],
+ )
+ ]
+ ),
+ x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/some.crl"
+ )
+ ],
+ relative_name=None,
+ reasons=frozenset([x509.ReasonFlags.aa_compromise]),
+ crl_issuer=None,
+ )
+ ]
+ ),
+ x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/some.crl"
+ )
+ ],
+ relative_name=None,
+ reasons=frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ x509.ReasonFlags.affiliation_changed,
+ x509.ReasonFlags.superseded,
+ x509.ReasonFlags.privilege_withdrawn,
+ x509.ReasonFlags.cessation_of_operation,
+ x509.ReasonFlags.aa_compromise,
+ x509.ReasonFlags.certificate_hold,
+ ]
),
- x509.NameAttribute(
- NameOID.COUNTRY_NAME,
- u"US"
+ crl_issuer=None,
+ )
+ ]
+ ),
+ x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ full_name=None,
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"indirect CRL for indirectCRL CA3",
+ ),
+ ]
),
- ]),
- reasons=None,
- crl_issuer=None,
- )
- ]),
- ]
+ reasons=None,
+ crl_issuer=None,
+ )
+ ]
+ ),
+ x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ full_name=None,
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"indirect CRL for indirectCRL CA3",
+ ),
+ x509.NameAttribute(
+ NameOID.COUNTRY_NAME, u"US"
+ ),
+ ]
+ ),
+ reasons=None,
+ crl_issuer=None,
+ )
+ ]
+ ),
+ ],
)
def test_ext(self, add_ext, backend):
issuer_private_key = RSA_KEY_2048.private_key(backend)
@@ -2639,21 +3211,21 @@ class TestCertificateBuilder(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- cert = x509.CertificateBuilder().subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
- ).public_key(
- subject_private_key.public_key()
- ).serial_number(
- 123
- ).add_extension(
- add_ext, critical=False
- ).sign(issuer_private_key, hashes.SHA256(), backend)
+ cert = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
+ .public_key(subject_private_key.public_key())
+ .serial_number(123)
+ .add_extension(add_ext, critical=False)
+ .sign(issuer_private_key, hashes.SHA256(), backend)
+ )
ext = cert.extensions.get_extension_for_class(type(add_ext))
assert ext.critical is False
@@ -2668,32 +3240,34 @@ class TestCertificateBuilder(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- cert = x509.CertificateBuilder().subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
- ).public_key(
- subject_private_key.public_key()
- ).serial_number(
- 123
- ).add_extension(
- x509.KeyUsage(
- digital_signature=True,
- content_commitment=True,
- key_encipherment=False,
- data_encipherment=False,
- key_agreement=False,
- key_cert_sign=True,
- crl_sign=False,
- encipher_only=False,
- decipher_only=False
- ),
- critical=False
- ).sign(issuer_private_key, hashes.SHA256(), backend)
+ cert = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
+ .public_key(subject_private_key.public_key())
+ .serial_number(123)
+ .add_extension(
+ x509.KeyUsage(
+ digital_signature=True,
+ content_commitment=True,
+ key_encipherment=False,
+ data_encipherment=False,
+ key_agreement=False,
+ key_cert_sign=True,
+ crl_sign=False,
+ encipher_only=False,
+ decipher_only=False,
+ ),
+ critical=False,
+ )
+ .sign(issuer_private_key, hashes.SHA256(), backend)
+ )
ext = cert.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
assert ext.critical is False
@@ -2706,7 +3280,7 @@ class TestCertificateBuilder(object):
key_cert_sign=True,
crl_sign=False,
encipher_only=False,
- decipher_only=False
+ decipher_only=False,
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -2714,14 +3288,18 @@ class TestCertificateBuilder(object):
def test_build_ca_request_with_path_length_none(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- request = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.ORGANIZATION_NAME,
- u'PyCA'),
- ])
- ).add_extension(
- x509.BasicConstraints(ca=True, path_length=None), critical=True
- ).sign(private_key, hashes.SHA1(), backend)
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name(
+ [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]
+ )
+ )
+ .add_extension(
+ x509.BasicConstraints(ca=True, path_length=None), critical=True
+ )
+ .sign(private_key, hashes.SHA1(), backend)
+ )
loaded_request = x509.load_pem_x509_csr(
request.public_bytes(encoding=serialization.Encoding.PEM), backend
@@ -2734,33 +3312,34 @@ class TestCertificateBuilder(object):
assert basic_constraints.value.path_length is None
@pytest.mark.parametrize(
- "unrecognized", [
+ "unrecognized",
+ [
x509.UnrecognizedExtension(
x509.ObjectIdentifier("1.2.3.4.5"),
b"abcdef",
)
- ]
+ ],
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_unrecognized_extension(self, backend, unrecognized):
private_key = RSA_KEY_2048.private_key(backend)
- cert = x509.CertificateBuilder().subject_name(
- x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
- ).issuer_name(
- x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
- ).not_valid_before(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).not_valid_after(
- datetime.datetime(2030, 12, 31, 8, 30)
- ).public_key(
- private_key.public_key()
- ).serial_number(
- 123
- ).add_extension(
- unrecognized, critical=False
- ).sign(private_key, hashes.SHA256(), backend)
+ cert = (
+ x509.CertificateBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US")])
+ )
+ .issuer_name(
+ x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US")])
+ )
+ .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
+ .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
+ .public_key(private_key.public_key())
+ .serial_number(123)
+ .add_extension(unrecognized, critical=False)
+ .sign(private_key, hashes.SHA256(), backend)
+ )
ext = cert.extensions.get_extension_for_oid(unrecognized.oid)
@@ -2777,39 +3356,73 @@ class TestCertificateSigningRequestBuilder(object):
x509.Name([])
)
with pytest.raises(TypeError):
- builder.sign(private_key, 'NotAHash', backend)
+ builder.sign(private_key, "NotAHash", backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_request_with_unsupported_hash_ed25519(self, backend):
+ private_key = ed25519.Ed25519PrivateKey.generate()
+ builder = x509.CertificateSigningRequestBuilder().subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+
+ with pytest.raises(ValueError):
+ builder.sign(private_key, hashes.SHA256(), backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_request_with_unsupported_hash_ed448(self, backend):
+ private_key = ed448.Ed448PrivateKey.generate()
+ builder = x509.CertificateSigningRequestBuilder().subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+
+ with pytest.raises(ValueError):
+ builder.sign(private_key, hashes.SHA256(), backend)
@pytest.mark.requires_backend_interface(interface=RSABackend)
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.hash_supported(hashes.MD5()),
+ skip_message="Requires OpenSSL with MD5 support",
+ )
def test_sign_rsa_with_md5(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
builder = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- ])
+ x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")])
)
request = builder.sign(private_key, hashes.MD5(), backend)
assert isinstance(request.signature_hash_algorithm, hashes.MD5)
@pytest.mark.requires_backend_interface(interface=DSABackend)
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.hash_supported(hashes.MD5()),
+ skip_message="Requires OpenSSL with MD5 support",
+ )
def test_sign_dsa_with_md5(self, backend):
private_key = DSA_KEY_2048.private_key(backend)
builder = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- ])
+ x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")])
)
with pytest.raises(ValueError):
builder.sign(private_key, hashes.MD5(), backend)
@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.hash_supported(hashes.MD5()),
+ skip_message="Requires OpenSSL with MD5 support",
+ )
def test_sign_ec_with_md5(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
private_key = EC_KEY_SECP256R1.private_key(backend)
builder = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- ])
+ x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")])
)
with pytest.raises(ValueError):
builder.sign(private_key, hashes.MD5(), backend)
@@ -2826,13 +3439,18 @@ class TestCertificateSigningRequestBuilder(object):
def test_build_ca_request_with_rsa(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- request = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- ])
- ).add_extension(
- x509.BasicConstraints(ca=True, path_length=2), critical=True
- ).sign(private_key, hashes.SHA1(), backend)
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name(
+ [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]
+ )
+ )
+ .add_extension(
+ x509.BasicConstraints(ca=True, path_length=2), critical=True
+ )
+ .sign(private_key, hashes.SHA1(), backend)
+ )
assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
public_key = request.public_key()
@@ -2840,7 +3458,7 @@ class TestCertificateSigningRequestBuilder(object):
subject = request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
]
basic_constraints = request.extensions.get_extension_for_oid(
ExtensionOID.BASIC_CONSTRAINTS
@@ -2852,14 +3470,22 @@ class TestCertificateSigningRequestBuilder(object):
def test_build_ca_request_with_unicode(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- request = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.ORGANIZATION_NAME,
- u'PyCA\U0001f37a'),
- ])
- ).add_extension(
- x509.BasicConstraints(ca=True, path_length=2), critical=True
- ).sign(private_key, hashes.SHA1(), backend)
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME, u"PyCA\U0001f37a"
+ ),
+ ]
+ )
+ )
+ .add_extension(
+ x509.BasicConstraints(ca=True, path_length=2), critical=True
+ )
+ .sign(private_key, hashes.SHA1(), backend)
+ )
loaded_request = x509.load_pem_x509_csr(
request.public_bytes(encoding=serialization.Encoding.PEM), backend
@@ -2867,67 +3493,95 @@ class TestCertificateSigningRequestBuilder(object):
subject = loaded_request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA\U0001f37a'),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA\U0001f37a"),
]
@pytest.mark.requires_backend_interface(interface=RSABackend)
def test_subject_dn_asn1_types(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- request = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u"value"),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"value"),
- x509.NameAttribute(NameOID.STREET_ADDRESS, u"value"),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"value"),
- x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"value"),
- x509.NameAttribute(NameOID.SERIAL_NUMBER, u"value"),
- x509.NameAttribute(NameOID.SURNAME, u"value"),
- x509.NameAttribute(NameOID.GIVEN_NAME, u"value"),
- x509.NameAttribute(NameOID.TITLE, u"value"),
- x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"value"),
- x509.NameAttribute(NameOID.X500_UNIQUE_IDENTIFIER, u"value"),
- x509.NameAttribute(NameOID.DN_QUALIFIER, u"value"),
- x509.NameAttribute(NameOID.PSEUDONYM, u"value"),
- x509.NameAttribute(NameOID.USER_ID, u"value"),
- x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"value"),
- x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"value"),
- x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, u"US"),
- x509.NameAttribute(
- NameOID.JURISDICTION_LOCALITY_NAME, u"value"
- ),
- x509.NameAttribute(
- NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, u"value"
- ),
- x509.NameAttribute(NameOID.BUSINESS_CATEGORY, u"value"),
- x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
- x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
- ])
- ).sign(private_key, hashes.SHA256(), backend)
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"value"),
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"value"
+ ),
+ x509.NameAttribute(NameOID.STREET_ADDRESS, u"value"),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME, u"value"
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATIONAL_UNIT_NAME, u"value"
+ ),
+ x509.NameAttribute(NameOID.SERIAL_NUMBER, u"value"),
+ x509.NameAttribute(NameOID.SURNAME, u"value"),
+ x509.NameAttribute(NameOID.GIVEN_NAME, u"value"),
+ x509.NameAttribute(NameOID.TITLE, u"value"),
+ x509.NameAttribute(
+ NameOID.GENERATION_QUALIFIER, u"value"
+ ),
+ x509.NameAttribute(
+ NameOID.X500_UNIQUE_IDENTIFIER, u"value"
+ ),
+ x509.NameAttribute(NameOID.DN_QUALIFIER, u"value"),
+ x509.NameAttribute(NameOID.PSEUDONYM, u"value"),
+ x509.NameAttribute(NameOID.USER_ID, u"value"),
+ x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"value"),
+ x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"value"),
+ x509.NameAttribute(
+ NameOID.JURISDICTION_COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.JURISDICTION_LOCALITY_NAME, u"value"
+ ),
+ x509.NameAttribute(
+ NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME,
+ u"value",
+ ),
+ x509.NameAttribute(
+ NameOID.BUSINESS_CATEGORY, u"value"
+ ),
+ x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
+ x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
+ ]
+ )
+ )
+ .sign(private_key, hashes.SHA256(), backend)
+ )
for oid, asn1_type in TestNameAttribute.EXPECTED_TYPES:
- assert request.subject.get_attributes_for_oid(
- oid
- )[0]._type == asn1_type
+ assert (
+ request.subject.get_attributes_for_oid(oid)[0]._type
+ == asn1_type
+ )
@pytest.mark.requires_backend_interface(interface=RSABackend)
def test_build_ca_request_with_multivalue_rdns(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- subject = x509.Name([
- x509.RelativeDistinguishedName([
- x509.NameAttribute(NameOID.TITLE, u'Test'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'Multivalue'),
- x509.NameAttribute(NameOID.SURNAME, u'RDNs'),
- ]),
- x509.RelativeDistinguishedName([
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA')
- ]),
- ])
-
- request = x509.CertificateSigningRequestBuilder().subject_name(
- subject
- ).sign(private_key, hashes.SHA1(), backend)
+ subject = x509.Name(
+ [
+ x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(NameOID.TITLE, u"Test"),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"Multivalue"),
+ x509.NameAttribute(NameOID.SURNAME, u"RDNs"),
+ ]
+ ),
+ x509.RelativeDistinguishedName(
+ [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]
+ ),
+ ]
+ )
+
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(subject)
+ .sign(private_key, hashes.SHA1(), backend)
+ )
loaded_request = x509.load_pem_x509_csr(
request.public_bytes(encoding=serialization.Encoding.PEM), backend
@@ -2939,13 +3593,17 @@ class TestCertificateSigningRequestBuilder(object):
def test_build_nonca_request_with_rsa(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- request = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])
- ).add_extension(
- x509.BasicConstraints(ca=False, path_length=None), critical=True,
- ).sign(private_key, hashes.SHA1(), backend)
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .add_extension(
+ x509.BasicConstraints(ca=False, path_length=None),
+ critical=True,
+ )
+ .sign(private_key, hashes.SHA1(), backend)
+ )
assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
public_key = request.public_key()
@@ -2953,7 +3611,7 @@ class TestCertificateSigningRequestBuilder(object):
subject = request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
]
basic_constraints = request.extensions.get_extension_for_oid(
ExtensionOID.BASIC_CONSTRAINTS
@@ -2966,13 +3624,22 @@ class TestCertificateSigningRequestBuilder(object):
_skip_curve_unsupported(backend, ec.SECP256R1())
private_key = ec.generate_private_key(ec.SECP256R1(), backend)
- request = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- ])
- ).add_extension(
- x509.BasicConstraints(ca=True, path_length=2), critical=True
- ).sign(private_key, hashes.SHA1(), backend)
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+ ),
+ ]
+ )
+ )
+ .add_extension(
+ x509.BasicConstraints(ca=True, path_length=2), critical=True
+ )
+ .sign(private_key, hashes.SHA1(), backend)
+ )
assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
public_key = request.public_key()
@@ -2980,7 +3647,85 @@ class TestCertificateSigningRequestBuilder(object):
subject = request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
+ ]
+ basic_constraints = request.extensions.get_extension_for_oid(
+ ExtensionOID.BASIC_CONSTRAINTS
+ )
+ assert basic_constraints.value.ca is True
+ assert basic_constraints.value.path_length == 2
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_build_ca_request_with_ed25519(self, backend):
+ private_key = ed25519.Ed25519PrivateKey.generate()
+
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+ ),
+ ]
+ )
+ )
+ .add_extension(
+ x509.BasicConstraints(ca=True, path_length=2), critical=True
+ )
+ .sign(private_key, None, backend)
+ )
+
+ assert request.signature_hash_algorithm is None
+ public_key = request.public_key()
+ assert isinstance(public_key, ed25519.Ed25519PublicKey)
+ subject = request.subject
+ assert isinstance(subject, x509.Name)
+ assert list(subject) == [
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
+ ]
+ basic_constraints = request.extensions.get_extension_for_oid(
+ ExtensionOID.BASIC_CONSTRAINTS
+ )
+ assert basic_constraints.value.ca is True
+ assert basic_constraints.value.path_length == 2
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_build_ca_request_with_ed448(self, backend):
+ private_key = ed448.Ed448PrivateKey.generate()
+
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+ ),
+ ]
+ )
+ )
+ .add_extension(
+ x509.BasicConstraints(ca=True, path_length=2), critical=True
+ )
+ .sign(private_key, None, backend)
+ )
+
+ assert request.signature_hash_algorithm is None
+ public_key = request.public_key()
+ assert isinstance(public_key, ed448.Ed448PublicKey)
+ subject = request.subject
+ assert isinstance(subject, x509.Name)
+ assert list(subject) == [
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
]
basic_constraints = request.extensions.get_extension_for_oid(
ExtensionOID.BASIC_CONSTRAINTS
@@ -2992,13 +3737,16 @@ class TestCertificateSigningRequestBuilder(object):
def test_build_ca_request_with_dsa(self, backend):
private_key = DSA_KEY_2048.private_key(backend)
- request = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])
- ).add_extension(
- x509.BasicConstraints(ca=True, path_length=2), critical=True
- ).sign(private_key, hashes.SHA1(), backend)
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .add_extension(
+ x509.BasicConstraints(ca=True, path_length=2), critical=True
+ )
+ .sign(private_key, hashes.SHA1(), backend)
+ )
assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
public_key = request.public_key()
@@ -3006,7 +3754,7 @@ class TestCertificateSigningRequestBuilder(object):
subject = request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
]
basic_constraints = request.extensions.get_extension_for_oid(
ExtensionOID.BASIC_CONSTRAINTS
@@ -3016,17 +3764,19 @@ class TestCertificateSigningRequestBuilder(object):
def test_add_duplicate_extension(self):
builder = x509.CertificateSigningRequestBuilder().add_extension(
- x509.BasicConstraints(True, 2), critical=True,
+ x509.BasicConstraints(True, 2),
+ critical=True,
)
with pytest.raises(ValueError):
builder.add_extension(
- x509.BasicConstraints(True, 2), critical=True,
+ x509.BasicConstraints(True, 2),
+ critical=True,
)
def test_set_invalid_subject(self):
builder = x509.CertificateSigningRequestBuilder()
with pytest.raises(TypeError):
- builder.subject_name('NotAName')
+ builder.subject_name("NotAName")
def test_add_invalid_extension_type(self):
builder = x509.CertificateSigningRequestBuilder()
@@ -3037,15 +3787,17 @@ class TestCertificateSigningRequestBuilder(object):
def test_add_unsupported_extension(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
builder = x509.CertificateSigningRequestBuilder()
- builder = builder.subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])
- ).add_extension(
- x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
- critical=False,
- ).add_extension(
- DummyExtension(), False
+ builder = (
+ builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .add_extension(
+ x509.SubjectAlternativeName(
+ [x509.DNSName(u"cryptography.io")]
+ ),
+ critical=False,
+ )
+ .add_extension(DummyExtension(), False)
)
with pytest.raises(NotImplementedError):
builder.sign(private_key, hashes.SHA256(), backend)
@@ -3053,24 +3805,26 @@ class TestCertificateSigningRequestBuilder(object):
def test_key_usage(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
builder = x509.CertificateSigningRequestBuilder()
- request = builder.subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])
- ).add_extension(
- x509.KeyUsage(
- digital_signature=True,
- content_commitment=True,
- key_encipherment=False,
- data_encipherment=False,
- key_agreement=False,
- key_cert_sign=True,
- crl_sign=False,
- encipher_only=False,
- decipher_only=False
- ),
- critical=False
- ).sign(private_key, hashes.SHA256(), backend)
+ request = (
+ builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .add_extension(
+ x509.KeyUsage(
+ digital_signature=True,
+ content_commitment=True,
+ key_encipherment=False,
+ data_encipherment=False,
+ key_agreement=False,
+ key_cert_sign=True,
+ crl_sign=False,
+ encipher_only=False,
+ decipher_only=False,
+ ),
+ critical=False,
+ )
+ .sign(private_key, hashes.SHA256(), backend)
+ )
assert len(request.extensions) == 1
ext = request.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
assert ext.critical is False
@@ -3083,30 +3837,32 @@ class TestCertificateSigningRequestBuilder(object):
key_cert_sign=True,
crl_sign=False,
encipher_only=False,
- decipher_only=False
+ decipher_only=False,
)
def test_key_usage_key_agreement_bit(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
builder = x509.CertificateSigningRequestBuilder()
- request = builder.subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])
- ).add_extension(
- x509.KeyUsage(
- digital_signature=False,
- content_commitment=False,
- key_encipherment=False,
- data_encipherment=False,
- key_agreement=True,
- key_cert_sign=True,
- crl_sign=False,
- encipher_only=False,
- decipher_only=True
- ),
- critical=False
- ).sign(private_key, hashes.SHA256(), backend)
+ request = (
+ builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .add_extension(
+ x509.KeyUsage(
+ digital_signature=False,
+ content_commitment=False,
+ key_encipherment=False,
+ data_encipherment=False,
+ key_agreement=True,
+ key_cert_sign=True,
+ crl_sign=False,
+ encipher_only=False,
+ decipher_only=True,
+ ),
+ critical=False,
+ )
+ .sign(private_key, hashes.SHA256(), backend)
+ )
assert len(request.extensions) == 1
ext = request.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
assert ext.critical is False
@@ -3119,20 +3875,27 @@ class TestCertificateSigningRequestBuilder(object):
key_cert_sign=True,
crl_sign=False,
encipher_only=False,
- decipher_only=True
+ decipher_only=True,
)
def test_add_two_extensions(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
builder = x509.CertificateSigningRequestBuilder()
- request = builder.subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).add_extension(
- x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
- critical=False,
- ).add_extension(
- x509.BasicConstraints(ca=True, path_length=2), critical=True
- ).sign(private_key, hashes.SHA1(), backend)
+ request = (
+ builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .add_extension(
+ x509.SubjectAlternativeName(
+ [x509.DNSName(u"cryptography.io")]
+ ),
+ critical=False,
+ )
+ .add_extension(
+ x509.BasicConstraints(ca=True, path_length=2), critical=True
+ )
+ .sign(private_key, hashes.SHA1(), backend)
+ )
assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
public_key = request.public_key()
@@ -3147,58 +3910,129 @@ class TestCertificateSigningRequestBuilder(object):
)
assert list(ext.value) == [x509.DNSName(u"cryptography.io")]
+ @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
+ def test_add_attributes(self, backend):
+ _skip_curve_unsupported(backend, ec.SECP256R1())
+ private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+ challenge_password = b"challenge me!"
+ unstructured_name = b"no structure, for shame"
+ locality = b"this shouldn't even be an X509 attribute"
+
+ request = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+ ),
+ ]
+ )
+ )
+ .add_attribute(
+ x509.oid.AttributeOID.CHALLENGE_PASSWORD, challenge_password
+ )
+ .add_attribute(
+ x509.oid.AttributeOID.UNSTRUCTURED_NAME, unstructured_name
+ )
+ .add_attribute(x509.oid.NameOID.LOCALITY_NAME, locality)
+ .sign(private_key, hashes.SHA256(), backend)
+ )
+
+ assert (
+ request.get_attribute_for_oid(
+ x509.oid.AttributeOID.CHALLENGE_PASSWORD
+ )
+ == challenge_password
+ )
+ assert (
+ request.get_attribute_for_oid(
+ x509.oid.AttributeOID.UNSTRUCTURED_NAME
+ )
+ == unstructured_name
+ )
+ assert (
+ request.get_attribute_for_oid(x509.oid.NameOID.LOCALITY_NAME)
+ == locality
+ )
+
+ def test_add_attribute_bad_types(self, backend):
+ request = x509.CertificateSigningRequestBuilder()
+ with pytest.raises(TypeError):
+ request.add_attribute(b"not an oid", b"val")
+
+ with pytest.raises(TypeError):
+ request.add_attribute(
+ x509.oid.AttributeOID.CHALLENGE_PASSWORD, 383
+ )
+
+ def test_duplicate_attribute(self, backend):
+ request = x509.CertificateSigningRequestBuilder().add_attribute(
+ x509.oid.AttributeOID.CHALLENGE_PASSWORD, b"val"
+ )
+ with pytest.raises(ValueError):
+ request.add_attribute(
+ x509.oid.AttributeOID.CHALLENGE_PASSWORD, b"val2"
+ )
+
def test_set_subject_twice(self):
builder = x509.CertificateSigningRequestBuilder()
builder = builder.subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
)
with pytest.raises(ValueError):
builder.subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
)
def test_subject_alt_names(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- san = x509.SubjectAlternativeName([
- x509.DNSName(u"example.com"),
- x509.DNSName(u"*.example.com"),
- x509.RegisteredID(x509.ObjectIdentifier("1.2.3.4.5.6.7")),
- x509.DirectoryName(x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u'PyCA'),
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME, u'We heart UTF8!\u2122'
- )
- ])),
- x509.IPAddress(ipaddress.ip_address(u"127.0.0.1")),
- x509.IPAddress(ipaddress.ip_address(u"ff::")),
- x509.OtherName(
- type_id=x509.ObjectIdentifier("1.2.3.3.3.3"),
- value=b"0\x03\x02\x01\x05"
- ),
- x509.RFC822Name(u"test@example.com"),
- x509.RFC822Name(u"email"),
- x509.RFC822Name(u"email@xn--eml-vla4c.com"),
- x509.UniformResourceIdentifier(
- u"https://xn--80ato2c.cryptography"
- ),
- x509.UniformResourceIdentifier(
- u"gopher://cryptography:70/some/path"
- ),
- ])
+ san = x509.SubjectAlternativeName(
+ [
+ x509.DNSName(u"example.com"),
+ x509.DNSName(u"*.example.com"),
+ x509.RegisteredID(x509.ObjectIdentifier("1.2.3.4.5.6.7")),
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.COMMON_NAME, u"PyCA"),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME,
+ u"We heart UTF8!\u2122",
+ ),
+ ]
+ )
+ ),
+ x509.IPAddress(ipaddress.ip_address(u"127.0.0.1")),
+ x509.IPAddress(ipaddress.ip_address(u"ff::")),
+ x509.OtherName(
+ type_id=x509.ObjectIdentifier("1.2.3.3.3.3"),
+ value=b"0\x03\x02\x01\x05",
+ ),
+ x509.RFC822Name(u"test@example.com"),
+ x509.RFC822Name(u"email"),
+ x509.RFC822Name(u"email@xn--eml-vla4c.com"),
+ x509.UniformResourceIdentifier(
+ u"https://xn--80ato2c.cryptography"
+ ),
+ x509.UniformResourceIdentifier(
+ u"gopher://cryptography:70/some/path"
+ ),
+ ]
+ )
- csr = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"SAN"),
- ])
- ).add_extension(
- san,
- critical=False,
- ).sign(private_key, hashes.SHA256(), backend)
+ csr = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")])
+ )
+ .add_extension(
+ san,
+ critical=False,
+ )
+ .sign(private_key, hashes.SHA256(), backend)
+ )
assert len(csr.extensions) == 1
ext = csr.extensions.get_extension_for_oid(
@@ -3211,18 +4045,22 @@ class TestCertificateSigningRequestBuilder(object):
def test_invalid_asn1_othername(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"SAN"),
- ])
- ).add_extension(
- x509.SubjectAlternativeName([
- x509.OtherName(
- type_id=x509.ObjectIdentifier("1.2.3.3.3.3"),
- value=b"\x01\x02\x01\x05"
+ builder = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")])
+ )
+ .add_extension(
+ x509.SubjectAlternativeName(
+ [
+ x509.OtherName(
+ type_id=x509.ObjectIdentifier("1.2.3.3.3.3"),
+ value=b"\x01\x02\x01\x05",
+ ),
+ ]
),
- ]),
- critical=False,
+ critical=False,
+ )
)
with pytest.raises(ValueError):
builder.sign(private_key, hashes.SHA256(), backend)
@@ -3230,13 +4068,15 @@ class TestCertificateSigningRequestBuilder(object):
def test_subject_alt_name_unsupported_general_name(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateSigningRequestBuilder().subject_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"SAN"),
- ])
- ).add_extension(
- x509.SubjectAlternativeName([FakeGeneralName("")]),
- critical=False,
+ builder = (
+ x509.CertificateSigningRequestBuilder()
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")])
+ )
+ .add_extension(
+ x509.SubjectAlternativeName([FakeGeneralName("")]),
+ critical=False,
+ )
)
with pytest.raises(ValueError):
@@ -3244,17 +4084,21 @@ class TestCertificateSigningRequestBuilder(object):
def test_extended_key_usage(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- eku = x509.ExtendedKeyUsage([
- ExtendedKeyUsageOID.CLIENT_AUTH,
- ExtendedKeyUsageOID.SERVER_AUTH,
- ExtendedKeyUsageOID.CODE_SIGNING,
- ])
+ eku = x509.ExtendedKeyUsage(
+ [
+ ExtendedKeyUsageOID.CLIENT_AUTH,
+ ExtendedKeyUsageOID.SERVER_AUTH,
+ ExtendedKeyUsageOID.CODE_SIGNING,
+ ]
+ )
builder = x509.CertificateSigningRequestBuilder()
- request = builder.subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).add_extension(
- eku, critical=False
- ).sign(private_key, hashes.SHA256(), backend)
+ request = (
+ builder.subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .add_extension(eku, critical=False)
+ .sign(private_key, hashes.SHA256(), backend)
+ )
ext = request.extensions.get_extension_for_oid(
ExtensionOID.EXTENDED_KEY_USAGE
@@ -3264,17 +4108,15 @@ class TestCertificateSigningRequestBuilder(object):
@pytest.mark.requires_backend_interface(interface=RSABackend)
def test_rsa_key_too_small(self, backend):
- private_key = rsa.generate_private_key(65537, 512, backend)
+ private_key = RSA_KEY_512.private_key(backend)
builder = x509.CertificateSigningRequestBuilder()
builder = builder.subject_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
)
- with pytest.raises(ValueError) as exc:
+ with pytest.raises(ValueError):
builder.sign(private_key, hashes.SHA512(), backend)
- assert str(exc.value) == "Digest too big for RSA key"
-
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_build_cert_with_aia(self, backend):
@@ -3284,31 +4126,34 @@ class TestCertificateSigningRequestBuilder(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- aia = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
- )
- ])
-
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).add_extension(
- aia, critical=False
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ aia = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ ]
+ )
+
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(aia, critical=False)
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
@@ -3320,6 +4165,46 @@ class TestCertificateSigningRequestBuilder(object):
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_build_cert_with_sia(self, backend):
+ issuer_private_key = RSA_KEY_2048.private_key(backend)
+ subject_private_key = RSA_KEY_2048.private_key(backend)
+
+ not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+ not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+ sia = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ ]
+ )
+
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(sia, critical=False)
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
+ )
+
+ cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
+
+ ext = cert.extensions.get_extension_for_oid(
+ ExtensionOID.SUBJECT_INFORMATION_ACCESS
+ )
+ assert ext.value == sia
+
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
def test_build_cert_with_ski(self, backend):
issuer_private_key = RSA_KEY_2048.private_key(backend)
subject_private_key = RSA_KEY_2048.private_key(backend)
@@ -3331,20 +4216,19 @@ class TestCertificateSigningRequestBuilder(object):
subject_private_key.public_key()
)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).add_extension(
- ski, critical=False
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(ski, critical=False)
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
@@ -3361,42 +4245,46 @@ class TestCertificateSigningRequestBuilder(object):
b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
b"\xcbY",
None,
- None
+ None,
),
x509.AuthorityKeyIdentifier(
b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
b"\xcbY",
[
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME, u"PyCA"
- ),
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"cryptography CA"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME, u"PyCA"
+ ),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography CA"
+ ),
+ ]
+ )
)
],
- 333
+ 333,
),
x509.AuthorityKeyIdentifier(
None,
[
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME, u"PyCA"
- ),
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"cryptography CA"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME, u"PyCA"
+ ),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography CA"
+ ),
+ ]
+ )
)
],
- 333
+ 333,
),
- ]
+ ],
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
@@ -3407,20 +4295,19 @@ class TestCertificateSigningRequestBuilder(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).add_extension(
- aki, critical=False
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(aki, critical=False)
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
@@ -3437,27 +4324,24 @@ class TestCertificateSigningRequestBuilder(object):
not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
- builder = x509.CertificateBuilder().serial_number(
- 777
- ).issuer_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).subject_name(x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- ])).public_key(
- subject_private_key.public_key()
- ).add_extension(
- x509.OCSPNoCheck(), critical=False
- ).not_valid_before(
- not_valid_before
- ).not_valid_after(
- not_valid_after
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(subject_private_key.public_key())
+ .add_extension(x509.OCSPNoCheck(), critical=False)
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
)
cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
- ext = cert.extensions.get_extension_for_oid(
- ExtensionOID.OCSP_NO_CHECK
- )
+ ext = cert.extensions.get_extension_for_oid(ExtensionOID.OCSP_NO_CHECK)
assert isinstance(ext.value, x509.OCSPNoCheck)
@@ -3468,7 +4352,7 @@ class TestDSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert isinstance(cert.signature_hash_algorithm, hashes.SHA1)
public_key = cert.public_key()
@@ -3483,7 +4367,8 @@ class TestDSACertificate(object):
"1b4bb7b81c2783da97cea62df67af5e85991fdc13aff10fc60e06586386"
"b96bb78d65750f542f86951e05a6d81baadbcd35a2e5cad4119923ae6a2"
"002091a3d17017f93c52970113cdc119970b9074ca506eac91c3dd37632"
- "5df4af6b3911ef267d26623a5a1c5df4a6d13f1c", 16
+ "5df4af6b3911ef267d26623a5a1c5df4a6d13f1c",
+ 16,
)
assert num.parameter_numbers.g == int(
"4b7ced71dc353965ecc10d441a9a06fc24943a32d66429dd5ef44d43e67"
@@ -3494,7 +4379,8 @@ class TestDSACertificate(object):
"3fbfa136205f130bee2cf5b9c38dc1095d4006f2e73335c07352c64130a"
"1ab2b89f13b48f628d3cc3868beece9bb7beade9f830eacc6fa241425c0"
"b3fcc0df416a0c89f7bf35668d765ec95cdcfbe9caff49cfc156c668c76"
- "fa6247676a6d3ac945844a083509c6a1b436baca", 16
+ "fa6247676a6d3ac945844a083509c6a1b436baca",
+ 16,
)
assert num.parameter_numbers.p == int(
"bfade6048e373cd4e48b677e878c8e5b08c02102ae04eb2cb5c46a523a3"
@@ -3505,7 +4391,8 @@ class TestDSACertificate(object):
"e703313743d86caa885930f62ed5bf342d8165627681e9cc3244ba72aa2"
"2148400a6bbe80154e855d042c9dc2a3405f1e517be9dea50562f56da93"
"f6085f844a7e705c1f043e65751c583b80d29103e590ccb26efdaa0893d"
- "833e36468f3907cfca788a3cb790f0341c8a31bf", 16
+ "833e36468f3907cfca788a3cb790f0341c8a31bf",
+ 16,
)
assert num.parameter_numbers.q == int(
"822ff5d234e073b901cf5941f58e1f538e71d40d", 16
@@ -3515,7 +4402,7 @@ class TestDSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert.signature == binascii.unhexlify(
b"302c021425c4a84a936ab311ee017d3cbd9a3c650bb3ae4a02145d30c64b4326"
@@ -3529,7 +4416,7 @@ class TestDSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert.tbs_certificate_bytes == binascii.unhexlify(
b"3082051aa003020102020900a37352e0b2142f86300906072a8648ce3804033"
@@ -3576,8 +4463,9 @@ class TestDSACertificate(object):
b"0b2142f86300c0603551d13040530030101ff"
)
cert.public_key().verify(
- cert.signature, cert.tbs_certificate_bytes,
- cert.signature_hash_algorithm
+ cert.signature,
+ cert.tbs_certificate_bytes,
+ cert.signature_hash_algorithm,
)
@@ -3589,13 +4477,13 @@ class TestDSACertificateRequest(object):
[
[
os.path.join("x509", "requests", "dsa_sha1.pem"),
- x509.load_pem_x509_csr
+ x509.load_pem_x509_csr,
],
[
os.path.join("x509", "requests", "dsa_sha1.der"),
- x509.load_der_x509_csr
+ x509.load_der_x509_csr,
],
- ]
+ ],
)
def test_load_dsa_request(self, path, loader_func, backend):
request = _load_cert(path, loader_func, backend)
@@ -3605,18 +4493,18 @@ class TestDSACertificateRequest(object):
subject = request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
]
def test_signature(self, backend):
request = _load_cert(
os.path.join("x509", "requests", "dsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert request.signature == binascii.unhexlify(
b"302c021461d58dc028d0110818a7d817d74235727c4acfdf0214097b52e198e"
@@ -3627,7 +4515,7 @@ class TestDSACertificateRequest(object):
request = _load_cert(
os.path.join("x509", "requests", "dsa_sha1.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert request.tbs_certrequest_bytes == binascii.unhexlify(
b"3082021802010030573118301606035504030c0f63727970746f677261706879"
@@ -3651,7 +4539,7 @@ class TestDSACertificateRequest(object):
request.public_key().verify(
request.signature,
request.tbs_certrequest_bytes,
- request.signature_hash_algorithm
+ request.signature_hash_algorithm,
)
@@ -3663,7 +4551,7 @@ class TestECDSACertificate(object):
cert = _load_cert(
os.path.join("x509", "ecdsa_root.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert isinstance(cert.signature_hash_algorithm, hashes.SHA384)
public_key = cert.public_key()
@@ -3671,11 +4559,13 @@ class TestECDSACertificate(object):
num = public_key.public_numbers()
assert num.x == int(
"dda7d9bb8ab80bfb0b7f21d2f0bebe73f3335d1abc34eadec69bbcd095f"
- "6f0ccd00bba615b51467e9e2d9fee8e630c17", 16
+ "6f0ccd00bba615b51467e9e2d9fee8e630c17",
+ 16,
)
assert num.y == int(
"ec0770f5cf842e40839ce83f416d3badd3a4145936789d0343ee10136c7"
- "2deae88a7a16bb543ce67dc23ff031ca3e23e", 16
+ "2deae88a7a16bb543ce67dc23ff031ca3e23e",
+ 16,
)
assert isinstance(num.curve, ec.SECP384R1)
@@ -3683,7 +4573,7 @@ class TestECDSACertificate(object):
cert = _load_cert(
os.path.join("x509", "ecdsa_root.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert.signature == binascii.unhexlify(
b"3065023100adbcf26c3f124ad12d39c30a099773f488368c8827bbe6888d5085"
@@ -3695,12 +4585,12 @@ class TestECDSACertificate(object):
assert r == int(
"adbcf26c3f124ad12d39c30a099773f488368c8827bbe6888d5085a763f99e32"
"de66930ff1ccb1098fdd6cabfa6b7fa0",
- 16
+ 16,
)
assert s == int(
"39665bc2648db89e50dca8d549a2edc7dcd1497f1701b8c8868f4e8c882ba89a"
"a98ac5d100bdf854e29ae55b7cb32717",
- 16
+ 16,
)
def test_tbs_certificate_bytes(self, backend):
@@ -3708,7 +4598,7 @@ class TestECDSACertificate(object):
cert = _load_cert(
os.path.join("x509", "ecdsa_root.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert cert.tbs_certificate_bytes == binascii.unhexlify(
b"308201c5a0030201020210055556bcf25ea43535c3a40fd5ab4572300a06082"
@@ -3728,8 +4618,9 @@ class TestECDSACertificate(object):
b"f9a1c5d8ae3641cc1163696229bc4bc6"
)
cert.public_key().verify(
- cert.signature, cert.tbs_certificate_bytes,
- ec.ECDSA(cert.signature_hash_algorithm)
+ cert.signature,
+ cert.tbs_certificate_bytes,
+ ec.ECDSA(cert.signature_hash_algorithm),
)
def test_load_ecdsa_no_named_curve(self, backend):
@@ -3737,7 +4628,7 @@ class TestECDSACertificate(object):
cert = _load_cert(
os.path.join("x509", "custom", "ec_no_named_curve.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
with pytest.raises(NotImplementedError):
cert.public_key()
@@ -3751,13 +4642,13 @@ class TestECDSACertificateRequest(object):
[
[
os.path.join("x509", "requests", "ec_sha256.pem"),
- x509.load_pem_x509_csr
+ x509.load_pem_x509_csr,
],
[
os.path.join("x509", "requests", "ec_sha256.der"),
- x509.load_der_x509_csr
+ x509.load_der_x509_csr,
],
- ]
+ ],
)
def test_load_ecdsa_certificate_request(self, path, loader_func, backend):
_skip_curve_unsupported(backend, ec.SECP384R1())
@@ -3768,11 +4659,11 @@ class TestECDSACertificateRequest(object):
subject = request.subject
assert isinstance(subject, x509.Name)
assert list(subject) == [
- x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- x509.NameAttribute(NameOID.LOCALITY_NAME, u'Austin'),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
]
def test_signature(self, backend):
@@ -3780,7 +4671,7 @@ class TestECDSACertificateRequest(object):
request = _load_cert(
os.path.join("x509", "requests", "ec_sha256.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert request.signature == binascii.unhexlify(
b"306502302c1a9f7de8c1787332d2307a886b476a59f172b9b0e250262f3238b1"
@@ -3794,7 +4685,7 @@ class TestECDSACertificateRequest(object):
request = _load_cert(
os.path.join("x509", "requests", "ec_sha256.pem"),
x509.load_pem_x509_csr,
- backend
+ backend,
)
assert request.tbs_certrequest_bytes == binascii.unhexlify(
b"3081d602010030573118301606035504030c0f63727970746f6772617068792"
@@ -3806,8 +4697,9 @@ class TestECDSACertificateRequest(object):
b"accff0ffaf7155812909d3726bd59fde001cff4bb9b2f5af8cbaa000"
)
request.public_key().verify(
- request.signature, request.tbs_certrequest_bytes,
- ec.ECDSA(request.signature_hash_algorithm)
+ request.signature,
+ request.tbs_certrequest_bytes,
+ ec.ECDSA(request.signature_hash_algorithm),
)
@@ -3827,14 +4719,12 @@ class TestOtherCertificate(object):
def test_bad_time_in_validity(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "badasn1time.pem"
- ),
+ os.path.join("x509", "badasn1time.pem"),
x509.load_pem_x509_certificate,
backend,
)
- with pytest.raises(ValueError, match='19020701025736Z'):
+ with pytest.raises(ValueError, match="19020701025736Z"):
cert.not_valid_after
@@ -3860,10 +4750,7 @@ class TestNameAttribute(object):
(NameOID.EMAIL_ADDRESS, _ASN1Type.IA5String),
(NameOID.JURISDICTION_COUNTRY_NAME, _ASN1Type.PrintableString),
(NameOID.JURISDICTION_LOCALITY_NAME, _ASN1Type.UTF8String),
- (
- NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME,
- _ASN1Type.UTF8String
- ),
+ (NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, _ASN1Type.UTF8String),
(NameOID.BUSINESS_CATEGORY, _ASN1Type.UTF8String),
(NameOID.POSTAL_ADDRESS, _ASN1Type.UTF8String),
(NameOID.POSTAL_CODE, _ASN1Type.UTF8String),
@@ -3882,32 +4769,23 @@ class TestNameAttribute(object):
def test_init_bad_oid(self):
with pytest.raises(TypeError):
- x509.NameAttribute(None, u'value')
+ x509.NameAttribute(None, u"value")
def test_init_bad_value(self):
with pytest.raises(TypeError):
- x509.NameAttribute(
- x509.ObjectIdentifier('2.999.1'),
- b'bytes'
- )
+ x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), b"bytes")
+
+ def test_init_none_value(self):
+ with pytest.raises(TypeError):
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, None)
def test_init_bad_country_code_value(self):
with pytest.raises(ValueError):
- x509.NameAttribute(
- NameOID.COUNTRY_NAME,
- u'United States'
- )
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"United States")
# unicode string of length 2, but > 2 bytes
with pytest.raises(ValueError):
- x509.NameAttribute(
- NameOID.COUNTRY_NAME,
- u'\U0001F37A\U0001F37A'
- )
-
- def test_init_empty_value(self):
- with pytest.raises(ValueError):
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'')
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"\U0001F37A\U0001F37A")
def test_invalid_type(self):
with pytest.raises(TypeError):
@@ -3915,28 +4793,23 @@ class TestNameAttribute(object):
def test_eq(self):
assert x509.NameAttribute(
- x509.ObjectIdentifier('2.999.1'), u'value'
- ) == x509.NameAttribute(
- x509.ObjectIdentifier('2.999.1'), u'value'
- )
+ x509.ObjectIdentifier("2.999.1"), u"value"
+ ) == x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value")
def test_ne(self):
assert x509.NameAttribute(
- x509.ObjectIdentifier('2.5.4.3'), u'value'
- ) != x509.NameAttribute(
- x509.ObjectIdentifier('2.5.4.5'), u'value'
- )
+ x509.ObjectIdentifier("2.5.4.3"), u"value"
+ ) != x509.NameAttribute(x509.ObjectIdentifier("2.5.4.5"), u"value")
assert x509.NameAttribute(
- x509.ObjectIdentifier('2.999.1'), u'value'
- ) != x509.NameAttribute(
- x509.ObjectIdentifier('2.999.1'), u'value2'
+ x509.ObjectIdentifier("2.999.1"), u"value"
+ ) != x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value2")
+ assert (
+ x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value")
+ != object()
)
- assert x509.NameAttribute(
- x509.ObjectIdentifier('2.999.2'), u'value'
- ) != object()
def test_repr(self):
- na = x509.NameAttribute(x509.ObjectIdentifier('2.5.4.3'), u'value')
+ na = x509.NameAttribute(x509.ObjectIdentifier("2.5.4.3"), u"value")
if not six.PY2:
assert repr(na) == (
"<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commo"
@@ -3951,14 +4824,19 @@ class TestNameAttribute(object):
def test_distinugished_name(self):
# Escaping
na = x509.NameAttribute(NameOID.COMMON_NAME, u'James "Jim" Smith, III')
- assert na.rfc4514_string() == r'CN=James \"Jim\" Smith\, III'
- na = x509.NameAttribute(NameOID.USER_ID, u'# escape+,;\0this ')
- assert na.rfc4514_string() == r'UID=\# escape\+\,\;\00this\ '
+ assert na.rfc4514_string() == r"CN=James \"Jim\" Smith\, III"
+ na = x509.NameAttribute(NameOID.USER_ID, u"# escape+,;\0this ")
+ assert na.rfc4514_string() == r"UID=\# escape\+\,\;\00this\ "
# Nonstandard attribute OID
- na = x509.NameAttribute(NameOID.EMAIL_ADDRESS, u'somebody@example.com')
- assert (na.rfc4514_string() ==
- '1.2.840.113549.1.9.1=somebody@example.com')
+ na = x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"somebody@example.com")
+ assert (
+ na.rfc4514_string() == "1.2.840.113549.1.9.1=somebody@example.com"
+ )
+
+ def test_empty_value(self):
+ na = x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"")
+ assert na.rfc4514_string() == r"ST="
class TestRelativeDistinguishedName(object):
@@ -3972,78 +4850,126 @@ class TestRelativeDistinguishedName(object):
def test_init_duplicate_attribute(self):
with pytest.raises(ValueError):
- x509.RelativeDistinguishedName([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'val1'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'val1'),
- ])
+ x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"val1"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"val1"
+ ),
+ ]
+ )
def test_hash(self):
- rdn1 = x509.RelativeDistinguishedName([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'),
- ])
- rdn2 = x509.RelativeDistinguishedName([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
- ])
- rdn3 = x509.RelativeDistinguishedName([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value3'),
- ])
+ rdn1 = x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"value1"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.2"), u"value2"
+ ),
+ ]
+ )
+ rdn2 = x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.2"), u"value2"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"value1"
+ ),
+ ]
+ )
+ rdn3 = x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"value1"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.2"), u"value3"
+ ),
+ ]
+ )
assert hash(rdn1) == hash(rdn2)
assert hash(rdn1) != hash(rdn3)
def test_eq(self):
- rdn1 = x509.RelativeDistinguishedName([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'),
- ])
- rdn2 = x509.RelativeDistinguishedName([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
- ])
+ rdn1 = x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"value1"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.2"), u"value2"
+ ),
+ ]
+ )
+ rdn2 = x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.2"), u"value2"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"value1"
+ ),
+ ]
+ )
assert rdn1 == rdn2
def test_ne(self):
- rdn1 = x509.RelativeDistinguishedName([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2'),
- ])
- rdn2 = x509.RelativeDistinguishedName([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value3'),
- ])
+ rdn1 = x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"value1"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.2"), u"value2"
+ ),
+ ]
+ )
+ rdn2 = x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"value1"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.2"), u"value3"
+ ),
+ ]
+ )
assert rdn1 != rdn2
assert rdn1 != object()
def test_iter_input(self):
# Order must be preserved too
attrs = [
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value2'),
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value3')
+ x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1"),
+ x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value2"),
+ x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value3"),
]
rdn = x509.RelativeDistinguishedName(iter(attrs))
assert list(rdn) == attrs
assert list(rdn) == attrs
def test_get_attributes_for_oid(self):
- oid = x509.ObjectIdentifier('2.999.1')
- attr = x509.NameAttribute(oid, u'value1')
+ oid = x509.ObjectIdentifier("2.999.1")
+ attr = x509.NameAttribute(oid, u"value1")
rdn = x509.RelativeDistinguishedName([attr])
assert rdn.get_attributes_for_oid(oid) == [attr]
- assert rdn.get_attributes_for_oid(x509.ObjectIdentifier('1.2.3')) == []
+ assert rdn.get_attributes_for_oid(x509.ObjectIdentifier("1.2.3")) == []
class TestObjectIdentifier(object):
def test_eq(self):
- oid1 = x509.ObjectIdentifier('2.999.1')
- oid2 = x509.ObjectIdentifier('2.999.1')
+ oid1 = x509.ObjectIdentifier("2.999.1")
+ oid2 = x509.ObjectIdentifier("2.999.1")
assert oid1 == oid2
def test_ne(self):
- oid1 = x509.ObjectIdentifier('2.999.1')
- assert oid1 != x509.ObjectIdentifier('2.999.2')
+ oid1 = x509.ObjectIdentifier("2.999.1")
+ assert oid1 != x509.ObjectIdentifier("2.999.2")
assert oid1 != object()
def test_repr(self):
@@ -4054,9 +4980,9 @@ class TestObjectIdentifier(object):
def test_name_property(self):
oid = x509.ObjectIdentifier("2.5.4.3")
- assert oid._name == 'commonName'
+ assert oid._name == "commonName"
oid = x509.ObjectIdentifier("2.999.1")
- assert oid._name == 'Unknown OID'
+ assert oid._name == "Unknown OID"
def test_too_short(self):
with pytest.raises(ValueError):
@@ -4084,21 +5010,23 @@ class TestObjectIdentifier(object):
class TestName(object):
def test_eq(self):
- ava1 = x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
- ava2 = x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
+ ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
+ ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
name1 = x509.Name([ava1, ava2])
- name2 = x509.Name([
- x509.RelativeDistinguishedName([ava1]),
- x509.RelativeDistinguishedName([ava2]),
- ])
+ name2 = x509.Name(
+ [
+ x509.RelativeDistinguishedName([ava1]),
+ x509.RelativeDistinguishedName([ava2]),
+ ]
+ )
name3 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])])
name4 = x509.Name([x509.RelativeDistinguishedName([ava2, ava1])])
assert name1 == name2
assert name3 == name4
def test_ne(self):
- ava1 = x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
- ava2 = x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
+ ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
+ ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
name1 = x509.Name([ava1, ava2])
name2 = x509.Name([ava2, ava1])
name3 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])])
@@ -4107,13 +5035,15 @@ class TestName(object):
assert name1 != object()
def test_hash(self):
- ava1 = x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
- ava2 = x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
+ ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
+ ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
name1 = x509.Name([ava1, ava2])
- name2 = x509.Name([
- x509.RelativeDistinguishedName([ava1]),
- x509.RelativeDistinguishedName([ava2]),
- ])
+ name2 = x509.Name(
+ [
+ x509.RelativeDistinguishedName([ava1]),
+ x509.RelativeDistinguishedName([ava2]),
+ ]
+ )
name3 = x509.Name([ava2, ava1])
name4 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])])
name5 = x509.Name([x509.RelativeDistinguishedName([ava2, ava1])])
@@ -4124,15 +5054,15 @@ class TestName(object):
def test_iter_input(self):
attrs = [
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
+ x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
]
name = x509.Name(iter(attrs))
assert list(name) == attrs
assert list(name) == attrs
def test_rdns(self):
- rdn1 = x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
- rdn2 = x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
+ rdn1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
+ rdn2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
name1 = x509.Name([rdn1, rdn2])
assert name1.rdns == [
x509.RelativeDistinguishedName([rdn1]),
@@ -4141,29 +5071,63 @@ class TestName(object):
name2 = x509.Name([x509.RelativeDistinguishedName([rdn1, rdn2])])
assert name2.rdns == [x509.RelativeDistinguishedName([rdn1, rdn2])]
- def test_repr(self):
- name = x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- ])
+ @pytest.mark.parametrize(
+ ("common_name", "org_name", "expected_repr"),
+ [
+ (
+ u"cryptography.io",
+ u"PyCA",
+ "<Name(CN=cryptography.io,O=PyCA)>",
+ ),
+ (
+ u"Certificación",
+ u"Certificación",
+ "<Name(CN=Certificación,O=Certificación)>",
+ ),
+ ],
+ )
+ def test_repr(self, common_name, org_name, expected_repr):
+ name = x509.Name(
+ [
+ x509.NameAttribute(NameOID.COMMON_NAME, common_name),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, org_name),
+ ]
+ )
- assert repr(name) == "<Name(CN=cryptography.io,O=PyCA)>"
+ assert repr(name) == expected_repr
def test_rfc4514_string(self):
- n = x509.Name([
- x509.RelativeDistinguishedName([
- x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'Sales'),
- x509.NameAttribute(NameOID.COMMON_NAME, u'J. Smith'),
- ]),
- x509.RelativeDistinguishedName([
- x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u'example'),
- ]),
- x509.RelativeDistinguishedName([
- x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u'net'),
- ]),
- ])
- assert (n.rfc4514_string() ==
- 'OU=Sales+CN=J. Smith,DC=example,DC=net')
+ n = x509.Name(
+ [
+ x509.RelativeDistinguishedName(
+ [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"net")]
+ ),
+ x509.RelativeDistinguishedName(
+ [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"example")]
+ ),
+ x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ NameOID.ORGANIZATIONAL_UNIT_NAME, u"Sales"
+ ),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"J. Smith"),
+ ]
+ ),
+ ]
+ )
+ assert n.rfc4514_string() == "OU=Sales+CN=J. Smith,DC=example,DC=net"
+
+ def test_rfc4514_string_empty_values(self):
+ n = x509.Name(
+ [
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u""),
+ x509.NameAttribute(NameOID.LOCALITY_NAME, u""),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
+ ]
+ )
+ assert n.rfc4514_string() == "CN=cryptography.io,O=PyCA,L=,ST=,C=US"
def test_not_nameattribute(self):
with pytest.raises(TypeError):
@@ -4171,10 +5135,12 @@ class TestName(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_bytes(self, backend):
- name = x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- ])
+ name = x509.Name(
+ [
+ x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ ]
+ )
assert name.public_bytes(backend) == binascii.unhexlify(
b"30293118301606035504030c0f63727970746f6772617068792e696f310d300"
b"b060355040a0c0450794341"
@@ -4185,19 +5151,150 @@ class TestName(object):
# For this test we need an odd length string. BMPString is UCS-2
# encoded so it will always be even length and OpenSSL will error if
# you pass an odd length string without encoding it properly first.
- name = x509.Name([
- x509.NameAttribute(
- NameOID.COMMON_NAME,
- u'cryptography.io',
- _ASN1Type.BMPString
- ),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'PyCA'),
- ])
+ name = x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"cryptography.io",
+ _ASN1Type.BMPString,
+ ),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ ]
+ )
assert name.public_bytes(backend) == binascii.unhexlify(
b"30383127302506035504031e1e00630072007900700074006f00670072006100"
b"7000680079002e0069006f310d300b060355040a0c0450794341"
)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_universalstring_bytes(self, backend):
+ # UniversalString is UCS-4
+ name = x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"cryptography.io",
+ _ASN1Type.UniversalString,
+ ),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ ]
+ )
+ assert name.public_bytes(backend) == binascii.unhexlify(
+ b"30563145304306035504031c3c00000063000000720000007900000070000000"
+ b"740000006f000000670000007200000061000000700000006800000079000000"
+ b"2e000000690000006f310d300b060355040a0c0450794341"
+ )
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+)
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestEd25519Certificate(object):
+ def test_load_pem_cert(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "ed25519", "root-ed25519.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ # self-signed, so this will work
+ cert.public_key().verify(cert.signature, cert.tbs_certificate_bytes)
+ assert isinstance(cert, x509.Certificate)
+ assert cert.serial_number == 9579446940964433301
+ assert cert.signature_hash_algorithm is None
+ assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED25519
+
+ def test_deepcopy(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "ed25519", "root-ed25519.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ assert copy.deepcopy(cert) is cert
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+)
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestEd448Certificate(object):
+ def test_load_pem_cert(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "ed448", "root-ed448.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ # self-signed, so this will work
+ cert.public_key().verify(cert.signature, cert.tbs_certificate_bytes)
+ assert isinstance(cert, x509.Certificate)
+ assert cert.serial_number == 448
+ assert cert.signature_hash_algorithm is None
+ assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED448
+
+
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestSignatureRejection(object):
+ """Test if signing rejects DH keys properly."""
+
+ def load_key(self, backend):
+ vector = load_vectors_from_file(
+ os.path.join("asymmetric", "DH", "rfc3526.txt"),
+ load_nist_vectors,
+ )[1]
+ p = int_from_bytes(binascii.unhexlify(vector["p"]), "big")
+ params = dh.DHParameterNumbers(p, int(vector["g"]))
+ param = params.parameters(backend)
+ return param.generate_private_key()
+
+ def test_crt_signing_check(self, backend):
+ issuer_private_key = self.load_key(backend)
+ public_key = RSA_KEY_2048.private_key(backend).public_key()
+ not_valid_before = datetime.datetime(2020, 1, 1, 1, 1)
+ not_valid_after = datetime.datetime(2050, 12, 31, 8, 30)
+ builder = (
+ x509.CertificateBuilder()
+ .serial_number(777)
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .public_key(public_key)
+ .not_valid_before(not_valid_before)
+ .not_valid_after(not_valid_after)
+ )
+
+ with pytest.raises(TypeError):
+ builder.sign(issuer_private_key, hashes.SHA256(), backend)
+
+ def test_csr_signing_check(self, backend):
+ private_key = self.load_key(backend)
+ builder = x509.CertificateSigningRequestBuilder().subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+
+ with pytest.raises(TypeError):
+ builder.sign(private_key, hashes.SHA256(), backend)
+
+ def test_crl_signing_check(self, backend):
+ private_key = self.load_key(backend)
+ last_time = datetime.datetime.utcnow().replace(microsecond=0)
+ next_time = last_time
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"CA")])
+ )
+ .last_update(last_time)
+ .next_update(next_time)
+ )
+
+ with pytest.raises(TypeError):
+ builder.sign(private_key, hashes.SHA256(), backend)
+
def test_random_serial_number(monkeypatch):
sample_data = os.urandom(20)
@@ -4210,7 +5307,5 @@ def test_random_serial_number(monkeypatch):
serial_number = x509.random_serial_number()
- assert (
- serial_number == utils.int_from_bytes(sample_data, "big") >> 1
- )
+ assert serial_number == utils.int_from_bytes(sample_data, "big") >> 1
assert serial_number.bit_length() < 160
diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py
index 5f220bcae..922d24917 100644
--- a/tests/x509/test_x509_crlbuilder.py
+++ b/tests/x509/test_x509_crlbuilder.py
@@ -12,11 +12,18 @@ import pytz
from cryptography import x509
from cryptography.hazmat.backends.interfaces import (
- DSABackend, EllipticCurveBackend, RSABackend, X509Backend
+ DSABackend,
+ EllipticCurveBackend,
+ RSABackend,
+ X509Backend,
)
from cryptography.hazmat.primitives import hashes
-from cryptography.hazmat.primitives.asymmetric import ec
-from cryptography.x509.oid import AuthorityInformationAccessOID, NameOID
+from cryptography.hazmat.primitives.asymmetric import ec, ed25519, ed448
+from cryptography.x509.oid import (
+ AuthorityInformationAccessOID,
+ NameOID,
+ SignatureAlgorithmOID,
+)
from ..hazmat.primitives.fixtures_dsa import DSA_KEY_2048
from ..hazmat.primitives.fixtures_ec import EC_KEY_SECP256R1
@@ -32,11 +39,11 @@ class TestCertificateRevocationListBuilder(object):
def test_set_issuer_name_twice(self):
builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
)
with pytest.raises(ValueError):
builder.issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -48,11 +55,20 @@ class TestCertificateRevocationListBuilder(object):
utc_last = datetime.datetime(2012, 1, 17, 6, 43)
next_time = datetime.datetime(2022, 1, 17, 6, 43)
private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(last_time).next_update(next_time)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_time)
+ .next_update(next_time)
+ )
crl = builder.sign(private_key, hashes.SHA256(), backend)
assert crl.last_update == utc_last
@@ -83,11 +99,20 @@ class TestCertificateRevocationListBuilder(object):
utc_next = datetime.datetime(2022, 1, 17, 6, 43)
last_time = datetime.datetime(2012, 1, 17, 6, 43)
private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(last_time).next_update(next_time)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_time)
+ .next_update(next_time)
+ )
crl = builder.sign(private_key, hashes.SHA256(), backend)
assert crl.next_update == utc_next
@@ -112,18 +137,14 @@ class TestCertificateRevocationListBuilder(object):
def test_last_update_after_next_update(self):
builder = x509.CertificateRevocationListBuilder()
- builder = builder.next_update(
- datetime.datetime(2002, 1, 1, 12, 1)
- )
+ builder = builder.next_update(datetime.datetime(2002, 1, 1, 12, 1))
with pytest.raises(ValueError):
builder.last_update(datetime.datetime(2003, 1, 1, 12, 1))
def test_next_update_after_last_update(self):
builder = x509.CertificateRevocationListBuilder()
- builder = builder.last_update(
- datetime.datetime(2002, 1, 1, 12, 1)
- )
+ builder = builder.last_update(datetime.datetime(2002, 1, 1, 12, 1))
with pytest.raises(ValueError):
builder.next_update(datetime.datetime(2001, 1, 1, 12, 1))
@@ -139,9 +160,7 @@ class TestCertificateRevocationListBuilder(object):
builder = x509.CertificateRevocationListBuilder()
with pytest.raises(TypeError):
- builder.add_extension(
- object(), False
- )
+ builder.add_extension(object(), False)
def test_add_invalid_revoked_certificate(self):
builder = x509.CertificateRevocationListBuilder()
@@ -153,10 +172,10 @@ class TestCertificateRevocationListBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_no_issuer_name(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateRevocationListBuilder().last_update(
- datetime.datetime(2002, 1, 1, 12, 1)
- ).next_update(
- datetime.datetime(2030, 1, 1, 12, 1)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .last_update(datetime.datetime(2002, 1, 1, 12, 1))
+ .next_update(datetime.datetime(2030, 1, 1, 12, 1))
)
with pytest.raises(ValueError):
@@ -166,10 +185,12 @@ class TestCertificateRevocationListBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_no_last_update(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).next_update(
- datetime.datetime(2030, 1, 1, 12, 1)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .next_update(datetime.datetime(2030, 1, 1, 12, 1))
)
with pytest.raises(ValueError):
@@ -179,10 +200,12 @@ class TestCertificateRevocationListBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_no_next_update(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
- ).last_update(
- datetime.datetime(2030, 1, 1, 12, 1)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
+ )
+ .last_update(datetime.datetime(2030, 1, 1, 12, 1))
)
with pytest.raises(ValueError):
@@ -194,11 +217,20 @@ class TestCertificateRevocationListBuilder(object):
private_key = RSA_KEY_2048.private_key(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(last_update).next_update(next_update)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ )
crl = builder.sign(private_key, hashes.SHA256(), backend)
assert len(crl) == 0
@@ -214,18 +246,20 @@ class TestCertificateRevocationListBuilder(object):
b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
b"\xcbY",
None,
- None
+ None,
),
- x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.DNSName(u"cryptography.io")
- )
- ]),
- x509.IssuerAlternativeName([
- x509.UniformResourceIdentifier(u"https://cryptography.io"),
- ])
- ]
+ x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.DNSName(u"cryptography.io"),
+ )
+ ]
+ ),
+ x509.IssuerAlternativeName(
+ [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+ ),
+ ],
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
@@ -233,16 +267,20 @@ class TestCertificateRevocationListBuilder(object):
private_key = RSA_KEY_2048.private_key(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
- ).add_extension(
- extension, False
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_extension(extension, False)
)
crl = builder.sign(private_key, hashes.SHA256(), backend)
@@ -258,22 +296,25 @@ class TestCertificateRevocationListBuilder(object):
private_key = RSA_KEY_2048.private_key(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- ian = x509.IssuerAlternativeName([
- x509.UniformResourceIdentifier(u"https://cryptography.io"),
- ])
+ ian = x509.IssuerAlternativeName(
+ [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+ )
crl_number = x509.CRLNumber(13)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
- ).add_extension(
- crl_number, False
- ).add_extension(
- ian, True
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_extension(crl_number, False)
+ .add_extension(ian, True)
)
crl = builder.sign(private_key, hashes.SHA256(), backend)
@@ -290,20 +331,66 @@ class TestCertificateRevocationListBuilder(object):
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_freshestcrl_extension(self, backend):
+ private_key = RSA_KEY_2048.private_key(backend)
+ last_update = datetime.datetime(2002, 1, 1, 12, 1)
+ next_update = datetime.datetime(2030, 1, 1, 12, 1)
+ freshest = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"http://d.om/delta")],
+ None,
+ None,
+ None,
+ )
+ ]
+ )
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_extension(freshest, False)
+ )
+
+ crl = builder.sign(private_key, hashes.SHA256(), backend)
+ assert len(crl) == 0
+ assert len(crl.extensions) == 1
+ ext1 = crl.extensions.get_extension_for_class(x509.FreshestCRL)
+ assert ext1.critical is False
+ assert isinstance(ext1.value[0], x509.DistributionPoint)
+ uri = ext1.value[0].full_name[0]
+ assert isinstance(uri, x509.UniformResourceIdentifier)
+ assert uri.value == u"http://d.om/delta"
+
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
def test_add_unsupported_extension(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
- ).add_extension(
- x509.OCSPNoCheck(), False
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_extension(x509.OCSPNoCheck(), False)
)
with pytest.raises(NotImplementedError):
builder.sign(private_key, hashes.SHA256(), backend)
@@ -314,14 +401,19 @@ class TestCertificateRevocationListBuilder(object):
private_key = RSA_KEY_512.private_key(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
)
with pytest.raises(ValueError):
@@ -333,19 +425,82 @@ class TestCertificateRevocationListBuilder(object):
private_key = RSA_KEY_2048.private_key(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
)
with pytest.raises(TypeError):
builder.sign(private_key, object(), backend)
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_sign_with_invalid_hash_ed25519(self, backend):
+ private_key = ed25519.Ed25519PrivateKey.generate()
+ last_update = datetime.datetime(2002, 1, 1, 12, 1)
+ next_update = datetime.datetime(2030, 1, 1, 12, 1)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ )
+
+ with pytest.raises(ValueError):
+ builder.sign(private_key, object(), backend)
+ with pytest.raises(ValueError):
+ builder.sign(private_key, hashes.SHA256(), backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_sign_with_invalid_hash_ed448(self, backend):
+ private_key = ed448.Ed448PrivateKey.generate()
+ last_update = datetime.datetime(2002, 1, 1, 12, 1)
+ next_update = datetime.datetime(2030, 1, 1, 12, 1)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ )
+
+ with pytest.raises(ValueError):
+ builder.sign(private_key, object(), backend)
+ with pytest.raises(ValueError):
+ builder.sign(private_key, hashes.SHA256(), backend)
+
@pytest.mark.requires_backend_interface(interface=DSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_sign_dsa_key(self, backend):
@@ -353,36 +508,42 @@ class TestCertificateRevocationListBuilder(object):
invalidity_date = x509.InvalidityDate(
datetime.datetime(2002, 1, 1, 0, 0)
)
- ian = x509.IssuerAlternativeName([
- x509.UniformResourceIdentifier(u"https://cryptography.io"),
- ])
- revoked_cert0 = x509.RevokedCertificateBuilder().serial_number(
- 2
- ).revocation_date(
- datetime.datetime(2012, 1, 1, 1, 1)
- ).add_extension(
- invalidity_date, False
- ).build(backend)
+ ian = x509.IssuerAlternativeName(
+ [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+ )
+ revoked_cert0 = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(2)
+ .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+ .add_extension(invalidity_date, False)
+ .build(backend)
+ )
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
- ).add_revoked_certificate(
- revoked_cert0
- ).add_extension(
- ian, False
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_revoked_certificate(revoked_cert0)
+ .add_extension(ian, False)
)
crl = builder.sign(private_key, hashes.SHA256(), backend)
- assert crl.extensions.get_extension_for_class(
- x509.IssuerAlternativeName
- ).value == ian
+ assert (
+ crl.extensions.get_extension_for_class(
+ x509.IssuerAlternativeName
+ ).value
+ == ian
+ )
assert crl[0].serial_number == revoked_cert0.serial_number
assert crl[0].revocation_date == revoked_cert0.revocation_date
assert len(crl[0].extensions) == 1
@@ -398,36 +559,152 @@ class TestCertificateRevocationListBuilder(object):
invalidity_date = x509.InvalidityDate(
datetime.datetime(2002, 1, 1, 0, 0)
)
- ian = x509.IssuerAlternativeName([
- x509.UniformResourceIdentifier(u"https://cryptography.io"),
- ])
- revoked_cert0 = x509.RevokedCertificateBuilder().serial_number(
- 2
- ).revocation_date(
- datetime.datetime(2012, 1, 1, 1, 1)
- ).add_extension(
- invalidity_date, False
- ).build(backend)
+ ian = x509.IssuerAlternativeName(
+ [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+ )
+ revoked_cert0 = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(2)
+ .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+ .add_extension(invalidity_date, False)
+ .build(backend)
+ )
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
- ).add_revoked_certificate(
- revoked_cert0
- ).add_extension(
- ian, False
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_revoked_certificate(revoked_cert0)
+ .add_extension(ian, False)
)
crl = builder.sign(private_key, hashes.SHA256(), backend)
- assert crl.extensions.get_extension_for_class(
- x509.IssuerAlternativeName
- ).value == ian
+ assert (
+ crl.extensions.get_extension_for_class(
+ x509.IssuerAlternativeName
+ ).value
+ == ian
+ )
+ assert crl[0].serial_number == revoked_cert0.serial_number
+ assert crl[0].revocation_date == revoked_cert0.revocation_date
+ assert len(crl[0].extensions) == 1
+ ext = crl[0].extensions.get_extension_for_class(x509.InvalidityDate)
+ assert ext.critical is False
+ assert ext.value == invalidity_date
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_sign_ed25519_key(self, backend):
+ private_key = ed25519.Ed25519PrivateKey.generate()
+ invalidity_date = x509.InvalidityDate(
+ datetime.datetime(2002, 1, 1, 0, 0)
+ )
+ ian = x509.IssuerAlternativeName(
+ [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+ )
+ revoked_cert0 = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(2)
+ .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+ .add_extension(invalidity_date, False)
+ .build(backend)
+ )
+ last_update = datetime.datetime(2002, 1, 1, 12, 1)
+ next_update = datetime.datetime(2030, 1, 1, 12, 1)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_revoked_certificate(revoked_cert0)
+ .add_extension(ian, False)
+ )
+
+ crl = builder.sign(private_key, None, backend)
+ assert crl.signature_hash_algorithm is None
+ assert crl.signature_algorithm_oid == SignatureAlgorithmOID.ED25519
+ assert (
+ crl.extensions.get_extension_for_class(
+ x509.IssuerAlternativeName
+ ).value
+ == ian
+ )
+ assert crl[0].serial_number == revoked_cert0.serial_number
+ assert crl[0].revocation_date == revoked_cert0.revocation_date
+ assert len(crl[0].extensions) == 1
+ ext = crl[0].extensions.get_extension_for_class(x509.InvalidityDate)
+ assert ext.critical is False
+ assert ext.value == invalidity_date
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_sign_ed448_key(self, backend):
+ private_key = ed448.Ed448PrivateKey.generate()
+ invalidity_date = x509.InvalidityDate(
+ datetime.datetime(2002, 1, 1, 0, 0)
+ )
+ ian = x509.IssuerAlternativeName(
+ [x509.UniformResourceIdentifier(u"https://cryptography.io")]
+ )
+ revoked_cert0 = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(2)
+ .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+ .add_extension(invalidity_date, False)
+ .build(backend)
+ )
+ last_update = datetime.datetime(2002, 1, 1, 12, 1)
+ next_update = datetime.datetime(2030, 1, 1, 12, 1)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_revoked_certificate(revoked_cert0)
+ .add_extension(ian, False)
+ )
+
+ crl = builder.sign(private_key, None, backend)
+ assert crl.signature_hash_algorithm is None
+ assert crl.signature_algorithm_oid == SignatureAlgorithmOID.ED448
+ assert (
+ crl.extensions.get_extension_for_class(
+ x509.IssuerAlternativeName
+ ).value
+ == ian
+ )
assert crl[0].serial_number == revoked_cert0.serial_number
assert crl[0].revocation_date == revoked_cert0.revocation_date
assert len(crl[0].extensions) == 1
@@ -441,11 +718,20 @@ class TestCertificateRevocationListBuilder(object):
private_key = DSA_KEY_2048.private_key(backend)
last_time = datetime.datetime(2012, 1, 16, 22, 43)
next_time = datetime.datetime(2022, 1, 17, 6, 43)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(last_time).next_update(next_time)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_time)
+ .next_update(next_time)
+ )
with pytest.raises(ValueError):
builder.sign(private_key, hashes.MD5(), backend)
@@ -457,11 +743,20 @@ class TestCertificateRevocationListBuilder(object):
private_key = EC_KEY_SECP256R1.private_key(backend)
last_time = datetime.datetime(2012, 1, 16, 22, 43)
next_time = datetime.datetime(2022, 1, 17, 6, 43)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(last_time).next_update(next_time)
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_time)
+ .next_update(next_time)
+ )
with pytest.raises(ValueError):
builder.sign(private_key, hashes.MD5(), backend)
@@ -475,30 +770,34 @@ class TestCertificateRevocationListBuilder(object):
invalidity_date = x509.InvalidityDate(
datetime.datetime(2002, 1, 1, 0, 0)
)
- revoked_cert0 = x509.RevokedCertificateBuilder().serial_number(
- 38
- ).revocation_date(
- datetime.datetime(2011, 1, 1, 1, 1)
- ).build(backend)
- revoked_cert1 = x509.RevokedCertificateBuilder().serial_number(
- 2
- ).revocation_date(
- datetime.datetime(2012, 1, 1, 1, 1)
- ).add_extension(
- invalidity_date, False
- ).build(backend)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
- ).add_revoked_certificate(
- revoked_cert0
- ).add_revoked_certificate(
- revoked_cert1
+ revoked_cert0 = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(38)
+ .revocation_date(datetime.datetime(2011, 1, 1, 1, 1))
+ .build(backend)
+ )
+ revoked_cert1 = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(2)
+ .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
+ .add_extension(invalidity_date, False)
+ .build(backend)
+ )
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_revoked_certificate(revoked_cert0)
+ .add_revoked_certificate(revoked_cert1)
)
crl = builder.sign(private_key, hashes.SHA256(), backend)
diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py
index 6de105fad..8e2b40271 100644
--- a/tests/x509/test_x509_ext.py
+++ b/tests/x509/test_x509_ext.py
@@ -9,53 +9,52 @@ import datetime
import ipaddress
import os
+import pretend
+
import pytest
import six
-from cryptography import utils, x509
+from cryptography import x509
from cryptography.hazmat.backends.interfaces import (
- DSABackend, EllipticCurveBackend, RSABackend, X509Backend
+ DSABackend,
+ EllipticCurveBackend,
+ RSABackend,
+ X509Backend,
)
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.x509 import DNSName, NameConstraints, SubjectAlternativeName
-from cryptography.x509.general_name import _lazy_import_idna
+from cryptography.x509.extensions import _key_identifier_from_public_key
from cryptography.x509.oid import (
- AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID,
- NameOID, ObjectIdentifier
+ AuthorityInformationAccessOID,
+ ExtendedKeyUsageOID,
+ ExtensionOID,
+ NameOID,
+ ObjectIdentifier,
+ SubjectInformationAccessOID,
+ _OID_NAMES,
)
from .test_x509 import _load_cert
from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048
from ..hazmat.primitives.test_ec import _skip_curve_unsupported
+from ..utils import load_vectors_from_file
def _make_certbuilder(private_key):
- name = x509.Name(
- [x509.NameAttribute(NameOID.COMMON_NAME, u'example.org')])
+ name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"example.org")])
return (
x509.CertificateBuilder()
- .subject_name(name)
- .issuer_name(name)
- .public_key(private_key.public_key())
- .serial_number(777)
- .not_valid_before(datetime.datetime(1999, 1, 1))
- .not_valid_after(datetime.datetime(2020, 1, 1))
+ .subject_name(name)
+ .issuer_name(name)
+ .public_key(private_key.public_key())
+ .serial_number(777)
+ .not_valid_before(datetime.datetime(1999, 1, 1))
+ .not_valid_after(datetime.datetime(2020, 1, 1))
)
-def test_lazy_idna_import():
- try:
- __import__("idna")
- pytest.skip("idna is installed")
- except ImportError:
- pass
-
- with pytest.raises(ImportError):
- _lazy_import_idna()
-
-
class TestExtension(object):
def test_not_an_oid(self):
bc = x509.BasicConstraints(ca=False, path_length=None)
@@ -77,26 +76,16 @@ class TestExtension(object):
)
def test_eq(self):
- ext1 = x509.Extension(
- x509.ObjectIdentifier('1.2.3.4'), False, 'value'
- )
- ext2 = x509.Extension(
- x509.ObjectIdentifier('1.2.3.4'), False, 'value'
- )
+ ext1 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), False, "value")
+ ext2 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), False, "value")
assert ext1 == ext2
def test_ne(self):
- ext1 = x509.Extension(
- x509.ObjectIdentifier('1.2.3.4'), False, 'value'
- )
- ext2 = x509.Extension(
- x509.ObjectIdentifier('1.2.3.5'), False, 'value'
- )
- ext3 = x509.Extension(
- x509.ObjectIdentifier('1.2.3.4'), True, 'value'
- )
+ ext1 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), False, "value")
+ ext2 = x509.Extension(x509.ObjectIdentifier("1.2.3.5"), False, "value")
+ ext3 = x509.Extension(x509.ObjectIdentifier("1.2.3.4"), True, "value")
ext4 = x509.Extension(
- x509.ObjectIdentifier('1.2.3.4'), False, 'value4'
+ x509.ObjectIdentifier("1.2.3.4"), False, "value4"
)
assert ext1 != ext2
assert ext1 != ext3
@@ -107,17 +96,17 @@ class TestExtension(object):
ext1 = x509.Extension(
ExtensionOID.BASIC_CONSTRAINTS,
False,
- x509.BasicConstraints(ca=False, path_length=None)
+ x509.BasicConstraints(ca=False, path_length=None),
)
ext2 = x509.Extension(
ExtensionOID.BASIC_CONSTRAINTS,
False,
- x509.BasicConstraints(ca=False, path_length=None)
+ x509.BasicConstraints(ca=False, path_length=None),
)
ext3 = x509.Extension(
ExtensionOID.BASIC_CONSTRAINTS,
False,
- x509.BasicConstraints(ca=True, path_length=None)
+ x509.BasicConstraints(ca=True, path_length=None),
)
assert hash(ext1) == hash(ext2)
assert hash(ext1) != hash(ext3)
@@ -146,10 +135,12 @@ class TestTLSFeature(object):
def test_ne(self):
ext1 = x509.TLSFeature([x509.TLSFeatureType.status_request])
ext2 = x509.TLSFeature([x509.TLSFeatureType.status_request_v2])
- ext3 = x509.TLSFeature([
- x509.TLSFeatureType.status_request,
- x509.TLSFeatureType.status_request_v2
- ])
+ ext3 = x509.TLSFeature(
+ [
+ x509.TLSFeatureType.status_request,
+ x509.TLSFeatureType.status_request_v2,
+ ]
+ )
assert ext1 != ext2
assert ext1 != ext3
assert ext1 != object()
@@ -157,10 +148,12 @@ class TestTLSFeature(object):
def test_hash(self):
ext1 = x509.TLSFeature([x509.TLSFeatureType.status_request])
ext2 = x509.TLSFeature([x509.TLSFeatureType.status_request])
- ext3 = x509.TLSFeature([
- x509.TLSFeatureType.status_request,
- x509.TLSFeatureType.status_request_v2
- ])
+ ext3 = x509.TLSFeature(
+ [
+ x509.TLSFeatureType.status_request,
+ x509.TLSFeatureType.status_request_v2,
+ ]
+ )
assert hash(ext1) == hash(ext2)
assert hash(ext1) != hash(ext3)
@@ -178,10 +171,12 @@ class TestTLSFeature(object):
assert list(ext2) == ext2_features
def test_indexing(self):
- ext = x509.TLSFeature([
- x509.TLSFeatureType.status_request,
- x509.TLSFeatureType.status_request_v2,
- ])
+ ext = x509.TLSFeature(
+ [
+ x509.TLSFeatureType.status_request,
+ x509.TLSFeatureType.status_request_v2,
+ ]
+ )
assert ext[-1] == ext[1]
assert ext[0] == x509.TLSFeatureType.status_request
@@ -245,10 +240,9 @@ class TestUnrecognizedExtension(object):
class TestCertificateIssuer(object):
def test_iter_names(self):
- ci = x509.CertificateIssuer([
- x509.DNSName(u"cryptography.io"),
- x509.DNSName(u"crypto.local"),
- ])
+ ci = x509.CertificateIssuer(
+ [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")]
+ )
assert len(ci) == 2
assert list(ci) == [
x509.DNSName(u"cryptography.io"),
@@ -256,13 +250,15 @@ class TestCertificateIssuer(object):
]
def test_indexing(self):
- ci = x509.CertificateIssuer([
- x509.DNSName(u"cryptography.io"),
- x509.DNSName(u"crypto.local"),
- x509.DNSName(u"another.local"),
- x509.RFC822Name(u"email@another.local"),
- x509.UniformResourceIdentifier(u"http://another.local"),
- ])
+ ci = x509.CertificateIssuer(
+ [
+ x509.DNSName(u"cryptography.io"),
+ x509.DNSName(u"crypto.local"),
+ x509.DNSName(u"another.local"),
+ x509.RFC822Name(u"email@another.local"),
+ x509.UniformResourceIdentifier(u"http://another.local"),
+ ]
+ )
assert ci[-1] == ci[4]
assert ci[2:6:2] == [ci[2], ci[4]]
@@ -291,9 +287,7 @@ class TestCertificateIssuer(object):
)
def test_get_values_for_type(self):
- ci = x509.CertificateIssuer(
- [x509.DNSName(u"cryptography.io")]
- )
+ ci = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")])
names = ci.get_values_for_type(x509.DNSName)
assert names == [u"cryptography.io"]
@@ -333,9 +327,7 @@ class TestCRLReason(object):
def test_repr(self):
reason1 = x509.CRLReason(x509.ReasonFlags.unspecified)
- assert repr(reason1) == (
- "<CRLReason(reason=ReasonFlags.unspecified)>"
- )
+ assert repr(reason1) == ("<CRLReason(reason=ReasonFlags.unspecified)>")
class TestDeltaCRLIndicator(object):
@@ -356,9 +348,7 @@ class TestDeltaCRLIndicator(object):
def test_repr(self):
delta1 = x509.DeltaCRLIndicator(2)
- assert repr(delta1) == (
- "<DeltaCRLIndicator(crl_number=2)>"
- )
+ assert repr(delta1) == ("<DeltaCRLIndicator(crl_number=2)>")
def test_hash(self):
delta1 = x509.DeltaCRLIndicator(1)
@@ -541,11 +531,11 @@ class TestPolicyInformation(object):
def test_eq(self):
pi = x509.PolicyInformation(
x509.ObjectIdentifier("1.2.3"),
- [u"string", x509.UserNotice(None, u"hi")]
+ [u"string", x509.UserNotice(None, u"hi")],
)
pi2 = x509.PolicyInformation(
x509.ObjectIdentifier("1.2.3"),
- [u"string", x509.UserNotice(None, u"hi")]
+ [u"string", x509.UserNotice(None, u"hi")],
)
assert pi == pi2
@@ -566,11 +556,11 @@ class TestPolicyInformation(object):
def test_hash(self):
pi = x509.PolicyInformation(
x509.ObjectIdentifier("1.2.3"),
- [u"string", x509.UserNotice(None, u"hi")]
+ [u"string", x509.UserNotice(None, u"hi")],
)
pi2 = x509.PolicyInformation(
x509.ObjectIdentifier("1.2.3"),
- [u"string", x509.UserNotice(None, u"hi")]
+ [u"string", x509.UserNotice(None, u"hi")],
)
pi3 = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), None)
assert hash(pi) == hash(pi2)
@@ -658,10 +648,9 @@ class TestCertificatePolicies(object):
cert = _load_cert(
os.path.join("x509", "bigoid.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
- ext = cert.extensions.get_extension_for_class(
- x509.CertificatePolicies)
+ ext = cert.extensions.get_extension_for_class(x509.CertificatePolicies)
oid = x509.ObjectIdentifier(
"1.3.6.1.4.1.311.21.8.8950086.10656446.2706058"
@@ -694,19 +683,21 @@ class TestCertificatePoliciesExtension(object):
cert = _load_cert(
os.path.join("x509", "custom", "cp_cps_uri.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cp = cert.extensions.get_extension_for_oid(
ExtensionOID.CERTIFICATE_POLICIES
).value
- assert cp == x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- [u"http://other.com/cps"]
- )
- ])
+ assert cp == x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [u"http://other.com/cps"],
+ )
+ ]
+ )
def test_user_notice_with_notice_reference(self, backend):
cert = _load_cert(
@@ -714,26 +705,28 @@ class TestCertificatePoliciesExtension(object):
"x509", "custom", "cp_user_notice_with_notice_reference.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cp = cert.extensions.get_extension_for_oid(
ExtensionOID.CERTIFICATE_POLICIES
).value
- assert cp == x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- [
- u"http://example.com/cps",
- u"http://other.com/cps",
- x509.UserNotice(
- x509.NoticeReference(u"my org", [1, 2, 3, 4]),
- u"thing"
- )
- ]
- )
- ])
+ assert cp == x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ u"http://example.com/cps",
+ u"http://other.com/cps",
+ x509.UserNotice(
+ x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+ u"thing",
+ ),
+ ],
+ )
+ ]
+ )
def test_user_notice_with_explicit_text(self, backend):
cert = _load_cert(
@@ -741,19 +734,21 @@ class TestCertificatePoliciesExtension(object):
"x509", "custom", "cp_user_notice_with_explicit_text.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cp = cert.extensions.get_extension_for_oid(
ExtensionOID.CERTIFICATE_POLICIES
).value
- assert cp == x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- [x509.UserNotice(None, u"thing")]
- )
- ])
+ assert cp == x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [x509.UserNotice(None, u"thing")],
+ )
+ ]
+ )
def test_user_notice_no_explicit_text(self, backend):
cert = _load_cert(
@@ -761,24 +756,25 @@ class TestCertificatePoliciesExtension(object):
"x509", "custom", "cp_user_notice_no_explicit_text.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cp = cert.extensions.get_extension_for_oid(
ExtensionOID.CERTIFICATE_POLICIES
).value
- assert cp == x509.CertificatePolicies([
- x509.PolicyInformation(
- x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
- [
- x509.UserNotice(
- x509.NoticeReference(u"my org", [1, 2, 3, 4]),
- None
- )
- ]
- )
- ])
+ assert cp == x509.CertificatePolicies(
+ [
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ x509.UserNotice(
+ x509.NoticeReference(u"my org", [1, 2, 3, 4]), None
+ )
+ ],
+ )
+ ]
+ )
class TestKeyUsage(object):
@@ -793,7 +789,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=True,
- decipher_only=False
+ decipher_only=False,
)
with pytest.raises(ValueError):
@@ -806,7 +802,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=True,
- decipher_only=True
+ decipher_only=True,
)
with pytest.raises(ValueError):
@@ -819,7 +815,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=True
+ decipher_only=True,
)
def test_properties_key_agreement_true(self):
@@ -832,7 +828,7 @@ class TestKeyUsage(object):
key_cert_sign=True,
crl_sign=False,
encipher_only=False,
- decipher_only=False
+ decipher_only=False,
)
assert ku.digital_signature is True
assert ku.content_commitment is True
@@ -852,7 +848,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=True
+ decipher_only=True,
)
assert ku.key_agreement is True
assert ku.encipher_only is False
@@ -868,7 +864,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=False
+ decipher_only=False,
)
assert ku.key_agreement is False
with pytest.raises(ValueError):
@@ -887,13 +883,13 @@ class TestKeyUsage(object):
key_cert_sign=True,
crl_sign=False,
encipher_only=False,
- decipher_only=False
+ decipher_only=False,
)
assert repr(ku) == (
"<KeyUsage(digital_signature=True, content_commitment=True, key_en"
"cipherment=False, data_encipherment=False, key_agreement=False, k"
- "ey_cert_sign=True, crl_sign=False, encipher_only=None, decipher_o"
- "nly=None)>"
+ "ey_cert_sign=True, crl_sign=False, encipher_only=False, decipher_"
+ "only=False)>"
)
def test_repr_key_agreement_true(self):
@@ -906,7 +902,7 @@ class TestKeyUsage(object):
key_cert_sign=True,
crl_sign=False,
encipher_only=False,
- decipher_only=False
+ decipher_only=False,
)
assert repr(ku) == (
"<KeyUsage(digital_signature=True, content_commitment=True, key_en"
@@ -925,7 +921,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=True
+ decipher_only=True,
)
ku2 = x509.KeyUsage(
digital_signature=False,
@@ -936,7 +932,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=True
+ decipher_only=True,
)
assert ku == ku2
@@ -950,7 +946,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=True
+ decipher_only=True,
)
ku2 = x509.KeyUsage(
digital_signature=False,
@@ -961,7 +957,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=False
+ decipher_only=False,
)
assert ku != ku2
assert ku != object()
@@ -976,7 +972,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=True
+ decipher_only=True,
)
ku2 = x509.KeyUsage(
digital_signature=False,
@@ -987,7 +983,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=True
+ decipher_only=True,
)
ku3 = x509.KeyUsage(
digital_signature=False,
@@ -998,7 +994,7 @@ class TestKeyUsage(object):
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
- decipher_only=False
+ decipher_only=False,
)
assert hash(ku) == hash(ku2)
assert hash(ku) != hash(ku3)
@@ -1019,15 +1015,15 @@ class TestSubjectKeyIdentifier(object):
assert repr(ext) == (
"<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
"eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
- "igest=b\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
- "\\xf7\\xff:\\xc9\')>)>"
+ "igest=b'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
+ "\\xf7\\xff:\\xc9')>)>"
)
else:
assert repr(ext) == (
"<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
"eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
- "igest=\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
- "\\xf7\\xff:\\xc9\')>)>"
+ "igest='\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
+ "\\xf7\\xff:\\xc9')>)>"
)
def test_eq(self):
@@ -1070,16 +1066,16 @@ class TestAuthorityKeyIdentifier(object):
def test_authority_cert_serial_number_not_integer(self):
dirname = x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- x509.ObjectIdentifier('2.999.1'),
- u'value1'
- ),
- x509.NameAttribute(
- x509.ObjectIdentifier('2.999.2'),
- u'value2'
- ),
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"value1"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.2"), u"value2"
+ ),
+ ]
+ )
)
with pytest.raises(TypeError):
x509.AuthorityKeyIdentifier(b"identifier", [dirname], "notanint")
@@ -1090,16 +1086,16 @@ class TestAuthorityKeyIdentifier(object):
def test_authority_issuer_not_none_serial_none(self):
dirname = x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- x509.ObjectIdentifier('2.999.1'),
- u'value1'
- ),
- x509.NameAttribute(
- x509.ObjectIdentifier('2.999.2'),
- u'value2'
- ),
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.1"), u"value1"
+ ),
+ x509.NameAttribute(
+ x509.ObjectIdentifier("2.999.2"), u"value2"
+ ),
+ ]
+ )
)
with pytest.raises(ValueError):
x509.AuthorityKeyIdentifier(b"identifier", [dirname], None)
@@ -1120,7 +1116,7 @@ class TestAuthorityKeyIdentifier(object):
def test_iter_input(self):
dirnames = [
x509.DirectoryName(
- x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
)
]
aki = x509.AuthorityKeyIdentifier(b"digest", iter(dirnames), 1234)
@@ -1128,7 +1124,7 @@ class TestAuthorityKeyIdentifier(object):
def test_repr(self):
dirname = x509.DirectoryName(
- x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
)
aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
@@ -1147,21 +1143,21 @@ class TestAuthorityKeyIdentifier(object):
def test_eq(self):
dirname = x509.DirectoryName(
- x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
)
aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
dirname2 = x509.DirectoryName(
- x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
)
aki2 = x509.AuthorityKeyIdentifier(b"digest", [dirname2], 1234)
assert aki == aki2
def test_ne(self):
dirname = x509.DirectoryName(
- x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
)
dirname5 = x509.DirectoryName(
- x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'aCN')])
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"aCN")])
)
aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
aki2 = x509.AuthorityKeyIdentifier(b"diges", [dirname], 1234)
@@ -1176,7 +1172,7 @@ class TestAuthorityKeyIdentifier(object):
def test_hash(self):
dirname = x509.DirectoryName(
- x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
+ x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")])
)
aki1 = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
aki2 = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
@@ -1207,9 +1203,7 @@ class TestBasicConstraints(object):
def test_repr(self):
na = x509.BasicConstraints(ca=True, path_length=None)
- assert repr(na) == (
- "<BasicConstraints(ca=True, path_length=None)>"
- )
+ assert repr(na) == ("<BasicConstraints(ca=True, path_length=None)>")
def test_hash(self):
na = x509.BasicConstraints(ca=True, path_length=None)
@@ -1238,14 +1232,16 @@ class TestExtendedKeyUsage(object):
x509.ExtendedKeyUsage(["notoid"])
def test_iter_len(self):
- eku = x509.ExtendedKeyUsage([
- x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
- x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
- ])
+ eku = x509.ExtendedKeyUsage(
+ [
+ x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
+ x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
+ ]
+ )
assert len(eku) == 2
assert list(eku) == [
ExtendedKeyUsageOID.SERVER_AUTH,
- ExtendedKeyUsageOID.CLIENT_AUTH
+ ExtendedKeyUsageOID.CLIENT_AUTH,
]
def test_iter_input(self):
@@ -1257,10 +1253,12 @@ class TestExtendedKeyUsage(object):
assert list(aia) == usages
def test_repr(self):
- eku = x509.ExtendedKeyUsage([
- x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
- x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
- ])
+ eku = x509.ExtendedKeyUsage(
+ [
+ x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
+ x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
+ ]
+ )
assert repr(eku) == (
"<ExtendedKeyUsage([<ObjectIdentifier(oid=1.3.6.1.5.5.7.3.1, name="
"serverAuth)>, <ObjectIdentifier(oid=1.3.6.1.5.5.7.3.2, name=clien"
@@ -1268,12 +1266,12 @@ class TestExtendedKeyUsage(object):
)
def test_eq(self):
- eku = x509.ExtendedKeyUsage([
- x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
- ])
- eku2 = x509.ExtendedKeyUsage([
- x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
- ])
+ eku = x509.ExtendedKeyUsage(
+ [x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")]
+ )
+ eku2 = x509.ExtendedKeyUsage(
+ [x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")]
+ )
assert eku == eku2
def test_ne(self):
@@ -1283,12 +1281,12 @@ class TestExtendedKeyUsage(object):
assert eku != object()
def test_hash(self):
- eku = x509.ExtendedKeyUsage([
- x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
- ])
- eku2 = x509.ExtendedKeyUsage([
- x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
- ])
+ eku = x509.ExtendedKeyUsage(
+ [x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")]
+ )
+ eku2 = x509.ExtendedKeyUsage(
+ [x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")]
+ )
eku3 = x509.ExtendedKeyUsage([x509.ObjectIdentifier("1.3.6")])
assert hash(eku) == hash(eku2)
assert hash(eku) != hash(eku3)
@@ -1301,7 +1299,7 @@ class TestExtensions(object):
cert = _load_cert(
os.path.join("x509", "verisign_md2_root.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions
assert len(ext) == 0
@@ -1317,7 +1315,7 @@ class TestExtensions(object):
"x509", "custom", "basic_constraints_not_critical.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
extensions = cert.extensions
ext = extensions.get_extension_for_oid(ExtensionOID.BASIC_CONSTRAINTS)
@@ -1326,11 +1324,9 @@ class TestExtensions(object):
def test_duplicate_extension(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "two_basic_constraints.pem"
- ),
+ os.path.join("x509", "custom", "two_basic_constraints.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
with pytest.raises(x509.DuplicateExtension) as exc:
cert.extensions
@@ -1343,7 +1339,7 @@ class TestExtensions(object):
"x509", "custom", "unsupported_extension_critical.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
x509.ObjectIdentifier("1.2.3.4")
@@ -1353,11 +1349,9 @@ class TestExtensions(object):
@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
def test_unsupported_extension(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "unsupported_extension_2.pem"
- ),
+ os.path.join("x509", "custom", "unsupported_extension_2.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
extensions = cert.extensions
assert len(extensions) == 2
@@ -1367,24 +1361,21 @@ class TestExtensions(object):
)
assert extensions[0].value == x509.UnrecognizedExtension(
x509.ObjectIdentifier("1.3.6.1.4.1.41482.2"),
- b"1.3.6.1.4.1.41482.1.2"
+ b"1.3.6.1.4.1.41482.1.2",
)
assert extensions[1].critical is False
assert extensions[1].oid == x509.ObjectIdentifier(
"1.3.6.1.4.1.45724.2.1.1"
)
assert extensions[1].value == x509.UnrecognizedExtension(
- x509.ObjectIdentifier("1.3.6.1.4.1.45724.2.1.1"),
- b"\x03\x02\x040"
+ x509.ObjectIdentifier("1.3.6.1.4.1.45724.2.1.1"), b"\x03\x02\x040"
)
def test_no_extensions_get_for_class(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "cryptography.io.pem"
- ),
+ os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
exts = cert.extensions
with pytest.raises(x509.ExtensionNotFound) as exc:
@@ -1400,7 +1391,7 @@ class TestExtensions(object):
cert = _load_cert(
os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
exts = cert.extensions
assert exts[-1] == exts[7]
@@ -1412,7 +1403,7 @@ class TestExtensions(object):
"x509", "custom", "basic_constraints_not_critical.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_class(x509.BasicConstraints)
assert ext is not None
@@ -1424,7 +1415,7 @@ class TestExtensions(object):
"x509", "custom", "basic_constraints_not_critical.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert repr(cert.extensions) == (
"<Extensions([<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name"
@@ -1442,7 +1433,7 @@ class TestBasicConstraintsExtension(object):
"x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.BASIC_CONSTRAINTS
@@ -1456,7 +1447,7 @@ class TestBasicConstraintsExtension(object):
cert = _load_cert(
os.path.join("x509", "custom", "bc_path_length_zero.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.BASIC_CONSTRAINTS
@@ -1470,7 +1461,7 @@ class TestBasicConstraintsExtension(object):
cert = _load_cert(
os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.BASIC_CONSTRAINTS
@@ -1484,7 +1475,7 @@ class TestBasicConstraintsExtension(object):
cert = _load_cert(
os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.BASIC_CONSTRAINTS
@@ -1500,10 +1491,10 @@ class TestBasicConstraintsExtension(object):
"x509",
"PKITS_data",
"certs",
- "ValidCertificatePathTest1EE.crt"
+ "ValidCertificatePathTest1EE.crt",
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
with pytest.raises(x509.ExtensionNotFound):
cert.extensions.get_extension_for_oid(
@@ -1516,7 +1507,7 @@ class TestBasicConstraintsExtension(object):
"x509", "custom", "basic_constraints_not_critical.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.BASIC_CONSTRAINTS
@@ -1533,7 +1524,7 @@ class TestSubjectKeyIdentifierExtension(object):
cert = _load_cert(
os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_KEY_IDENTIFIER
@@ -1551,7 +1542,7 @@ class TestSubjectKeyIdentifierExtension(object):
cert = _load_cert(
os.path.join("x509", "custom", "bc_path_length_zero.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
with pytest.raises(x509.ExtensionNotFound):
cert.extensions.get_extension_for_oid(
@@ -1564,14 +1555,12 @@ class TestSubjectKeyIdentifierExtension(object):
cert = _load_cert(
os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_KEY_IDENTIFIER
)
- ski = x509.SubjectKeyIdentifier.from_public_key(
- cert.public_key()
- )
+ ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key())
assert ext.value == ski
@pytest.mark.requires_backend_interface(interface=DSABackend)
@@ -1580,17 +1569,49 @@ class TestSubjectKeyIdentifierExtension(object):
cert = _load_cert(
os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_KEY_IDENTIFIER
)
- ski = x509.SubjectKeyIdentifier.from_public_key(
- cert.public_key()
- )
+ ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key())
assert ext.value == ski
+ @pytest.mark.requires_backend_interface(interface=DSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_invalid_bit_string_padding_from_public_key(self, backend):
+ data = load_vectors_from_file(
+ filename=os.path.join(
+ "asymmetric",
+ "DER_Serialization",
+ "dsa_public_key_invalid_bit_string.der",
+ ),
+ loader=lambda data: data.read(),
+ mode="rb",
+ )
+ pretend_key = pretend.stub(public_bytes=lambda x, y: data)
+ with pytest.raises(ValueError):
+ _key_identifier_from_public_key(pretend_key)
+
+ @pytest.mark.requires_backend_interface(interface=DSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_no_optional_params_allowed_from_public_key(self, backend):
+ data = load_vectors_from_file(
+ filename=os.path.join(
+ "asymmetric",
+ "DER_Serialization",
+ "dsa_public_key_no_params.der",
+ ),
+ loader=lambda data: data.read(),
+ mode="rb",
+ )
+ pretend_key = pretend.stub(public_bytes=lambda x, y: data)
+ key_identifier = _key_identifier_from_public_key(pretend_key)
+ assert key_identifier == binascii.unhexlify(
+ b"24c0133a6a492f2c48a18c7648e515db5ac76749"
+ )
+
@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_from_ec_public_key(self, backend):
@@ -1598,15 +1619,49 @@ class TestSubjectKeyIdentifierExtension(object):
cert = _load_cert(
os.path.join("x509", "ecdsa_root.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_KEY_IDENTIFIER
)
- ski = x509.SubjectKeyIdentifier.from_public_key(
- cert.public_key()
+ ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key())
+ assert ext.value == ski
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed25519_supported(),
+ skip_message="Requires OpenSSL with Ed25519 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_from_ed25519_public_key(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "ed25519", "root-ed25519.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
)
+
+ ext = cert.extensions.get_extension_for_oid(
+ ExtensionOID.SUBJECT_KEY_IDENTIFIER
+ )
+ ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key())
+ assert ext.value == ski
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.ed448_supported(),
+ skip_message="Requires OpenSSL with Ed448 support",
+ )
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_from_ed448_public_key(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "ed448", "root-ed448.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+
+ ext = cert.extensions.get_extension_for_oid(
+ ExtensionOID.SUBJECT_KEY_IDENTIFIER
+ )
+ ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key())
assert ext.value == ski
@@ -1617,7 +1672,7 @@ class TestKeyUsageExtension(object):
cert = _load_cert(
os.path.join("x509", "verisign_md2_root.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions
with pytest.raises(x509.ExtensionNotFound) as exc:
@@ -1627,11 +1682,9 @@ class TestKeyUsageExtension(object):
def test_all_purposes(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "all_key_usages.pem"
- ),
+ os.path.join("x509", "custom", "all_key_usages.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
extensions = cert.extensions
ext = extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
@@ -1654,7 +1707,7 @@ class TestKeyUsageExtension(object):
"x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
assert ext is not None
@@ -1671,15 +1724,9 @@ class TestKeyUsageExtension(object):
class TestDNSName(object):
- def test_init_deprecated(self):
- pytest.importorskip("idna")
- with pytest.warns(utils.DeprecatedIn21):
- name = x509.DNSName(u".\xf5\xe4\xf6\xfc.example.com")
- assert name.value == u".xn--4ca7aey.example.com"
-
- with pytest.warns(utils.DeprecatedIn21):
- name = x509.DNSName(u"\xf5\xe4\xf6\xfc.example.com")
- assert name.value == u"xn--4ca7aey.example.com"
+ def test_non_a_label(self):
+ with pytest.raises(ValueError):
+ x509.DNSName(u".\xf5\xe4\xf6\xfc.example.com")
def test_init(self):
name = x509.DNSName(u"*.xn--4ca7aey.example.com")
@@ -1715,40 +1762,40 @@ class TestDirectoryName(object):
x509.DirectoryName(1.3)
def test_repr(self):
- name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'value1')])
+ name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"value1")])
gn = x509.DirectoryName(name)
assert repr(gn) == "<DirectoryName(value=<Name(CN=value1)>)>"
def test_eq(self):
- name = x509.Name([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
- ])
- name2 = x509.Name([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
- ])
+ name = x509.Name(
+ [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")]
+ )
+ name2 = x509.Name(
+ [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")]
+ )
gn = x509.DirectoryName(name)
gn2 = x509.DirectoryName(name2)
assert gn == gn2
def test_ne(self):
- name = x509.Name([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
- ])
- name2 = x509.Name([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
- ])
+ name = x509.Name(
+ [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")]
+ )
+ name2 = x509.Name(
+ [x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")]
+ )
gn = x509.DirectoryName(name)
gn2 = x509.DirectoryName(name2)
assert gn != gn2
assert gn != object()
def test_hash(self):
- name = x509.Name([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
- ])
- name2 = x509.Name([
- x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
- ])
+ name = x509.Name(
+ [x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")]
+ )
+ name2 = x509.Name(
+ [x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")]
+ )
gn = x509.DirectoryName(name)
gn2 = x509.DirectoryName(name)
gn3 = x509.DirectoryName(name2)
@@ -1790,15 +1837,9 @@ class TestRFC822Name(object):
gn = x509.RFC822Name(u"administrator")
assert gn.value == u"administrator"
- def test_idna(self):
- pytest.importorskip("idna")
- with pytest.warns(utils.DeprecatedIn21):
- gn = x509.RFC822Name(u"email@em\xe5\xefl.com")
-
- assert gn.value == u"email@xn--eml-vla4c.com"
-
- gn2 = x509.RFC822Name(u"email@xn--eml-vla4c.com")
- assert gn2.value == u"email@xn--eml-vla4c.com"
+ def test_non_a_label(self):
+ with pytest.raises(ValueError):
+ x509.RFC822Name(u"email@em\xe5\xefl.com")
def test_hash(self):
g1 = x509.RFC822Name(u"email@host.com")
@@ -1830,41 +1871,16 @@ class TestUniformResourceIdentifier(object):
gn = x509.UniformResourceIdentifier(u"singlelabel:443/test")
assert gn.value == u"singlelabel:443/test"
- def test_idna_no_port(self):
- pytest.importorskip("idna")
- with pytest.warns(utils.DeprecatedIn21):
- gn = x509.UniformResourceIdentifier(
+ def test_non_a_label(self):
+ with pytest.raises(ValueError):
+ x509.UniformResourceIdentifier(
u"http://\u043f\u044b\u043a\u0430.cryptography"
)
- assert gn.value == u"http://xn--80ato2c.cryptography"
-
- def test_idna_with_port(self):
- pytest.importorskip("idna")
- with pytest.warns(utils.DeprecatedIn21):
- gn = x509.UniformResourceIdentifier(
- u"gopher://\u043f\u044b\u043a\u0430.cryptography:70/some/path"
- )
-
- assert gn.value == (
- u"gopher://xn--80ato2c.cryptography:70/some/path"
- )
-
def test_empty_hostname(self):
gn = x509.UniformResourceIdentifier(u"ldap:///some-nonsense")
assert gn.value == "ldap:///some-nonsense"
- def test_query_and_fragment(self):
- pytest.importorskip("idna")
- with pytest.warns(utils.DeprecatedIn21):
- gn = x509.UniformResourceIdentifier(
- u"ldap://\u043f\u044b\u043a\u0430.cryptography:90/path?query="
- u"true#somedata"
- )
- assert gn.value == (
- u"ldap://xn--80ato2c.cryptography:90/path?query=true#somedata"
- )
-
def test_hash(self):
g1 = x509.UniformResourceIdentifier(u"http://host.com")
g2 = x509.UniformResourceIdentifier(u"http://host.com")
@@ -1876,13 +1892,9 @@ class TestUniformResourceIdentifier(object):
def test_repr(self):
gn = x509.UniformResourceIdentifier(u"string")
if not six.PY2:
- assert repr(gn) == (
- "<UniformResourceIdentifier(value='string')>"
- )
+ assert repr(gn) == ("<UniformResourceIdentifier(value='string')>")
else:
- assert repr(gn) == (
- "<UniformResourceIdentifier(value=u'string')>"
- )
+ assert repr(gn) == ("<UniformResourceIdentifier(value=u'string')>")
class TestRegisteredID(object):
@@ -2017,17 +2029,14 @@ class TestOtherName(object):
class TestGeneralNames(object):
def test_get_values_for_type(self):
- gns = x509.GeneralNames(
- [x509.DNSName(u"cryptography.io")]
- )
+ gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")])
names = gns.get_values_for_type(x509.DNSName)
assert names == [u"cryptography.io"]
def test_iter_names(self):
- gns = x509.GeneralNames([
- x509.DNSName(u"cryptography.io"),
- x509.DNSName(u"crypto.local"),
- ])
+ gns = x509.GeneralNames(
+ [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")]
+ )
assert len(gns) == 2
assert list(gns) == [
x509.DNSName(u"cryptography.io"),
@@ -2043,28 +2052,24 @@ class TestGeneralNames(object):
assert list(gns) == names
def test_indexing(self):
- gn = x509.GeneralNames([
- x509.DNSName(u"cryptography.io"),
- x509.DNSName(u"crypto.local"),
- x509.DNSName(u"another.local"),
- x509.RFC822Name(u"email@another.local"),
- x509.UniformResourceIdentifier(u"http://another.local"),
- ])
+ gn = x509.GeneralNames(
+ [
+ x509.DNSName(u"cryptography.io"),
+ x509.DNSName(u"crypto.local"),
+ x509.DNSName(u"another.local"),
+ x509.RFC822Name(u"email@another.local"),
+ x509.UniformResourceIdentifier(u"http://another.local"),
+ ]
+ )
assert gn[-1] == gn[4]
assert gn[2:6:2] == [gn[2], gn[4]]
def test_invalid_general_names(self):
with pytest.raises(TypeError):
- x509.GeneralNames(
- [x509.DNSName(u"cryptography.io"), "invalid"]
- )
+ x509.GeneralNames([x509.DNSName(u"cryptography.io"), "invalid"])
def test_repr(self):
- gns = x509.GeneralNames(
- [
- x509.DNSName(u"cryptography.io")
- ]
- )
+ gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")])
if not six.PY2:
assert repr(gns) == (
"<GeneralNames([<DNSName(value='cryptography.io')>])>"
@@ -2075,21 +2080,13 @@ class TestGeneralNames(object):
)
def test_eq(self):
- gns = x509.GeneralNames(
- [x509.DNSName(u"cryptography.io")]
- )
- gns2 = x509.GeneralNames(
- [x509.DNSName(u"cryptography.io")]
- )
+ gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")])
+ gns2 = x509.GeneralNames([x509.DNSName(u"cryptography.io")])
assert gns == gns2
def test_ne(self):
- gns = x509.GeneralNames(
- [x509.DNSName(u"cryptography.io")]
- )
- gns2 = x509.GeneralNames(
- [x509.RFC822Name(u"admin@cryptography.io")]
- )
+ gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")])
+ gns2 = x509.GeneralNames([x509.RFC822Name(u"admin@cryptography.io")])
assert gns != gns2
assert gns != object()
@@ -2103,17 +2100,14 @@ class TestGeneralNames(object):
class TestIssuerAlternativeName(object):
def test_get_values_for_type(self):
- san = x509.IssuerAlternativeName(
- [x509.DNSName(u"cryptography.io")]
- )
+ san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
names = san.get_values_for_type(x509.DNSName)
assert names == [u"cryptography.io"]
def test_iter_names(self):
- san = x509.IssuerAlternativeName([
- x509.DNSName(u"cryptography.io"),
- x509.DNSName(u"crypto.local"),
- ])
+ san = x509.IssuerAlternativeName(
+ [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")]
+ )
assert len(san) == 2
assert list(san) == [
x509.DNSName(u"cryptography.io"),
@@ -2121,13 +2115,15 @@ class TestIssuerAlternativeName(object):
]
def test_indexing(self):
- ian = x509.IssuerAlternativeName([
- x509.DNSName(u"cryptography.io"),
- x509.DNSName(u"crypto.local"),
- x509.DNSName(u"another.local"),
- x509.RFC822Name(u"email@another.local"),
- x509.UniformResourceIdentifier(u"http://another.local"),
- ])
+ ian = x509.IssuerAlternativeName(
+ [
+ x509.DNSName(u"cryptography.io"),
+ x509.DNSName(u"crypto.local"),
+ x509.DNSName(u"another.local"),
+ x509.RFC822Name(u"email@another.local"),
+ x509.UniformResourceIdentifier(u"http://another.local"),
+ ]
+ )
assert ian[-1] == ian[4]
assert ian[2:6:2] == [ian[2], ian[4]]
@@ -2138,11 +2134,7 @@ class TestIssuerAlternativeName(object):
)
def test_repr(self):
- san = x509.IssuerAlternativeName(
- [
- x509.DNSName(u"cryptography.io")
- ]
- )
+ san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
if not six.PY2:
assert repr(san) == (
"<IssuerAlternativeName("
@@ -2155,18 +2147,12 @@ class TestIssuerAlternativeName(object):
)
def test_eq(self):
- san = x509.IssuerAlternativeName(
- [x509.DNSName(u"cryptography.io")]
- )
- san2 = x509.IssuerAlternativeName(
- [x509.DNSName(u"cryptography.io")]
- )
+ san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
+ san2 = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
assert san == san2
def test_ne(self):
- san = x509.IssuerAlternativeName(
- [x509.DNSName(u"cryptography.io")]
- )
+ san = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
san2 = x509.IssuerAlternativeName(
[x509.RFC822Name(u"admin@cryptography.io")]
)
@@ -2228,17 +2214,14 @@ class TestCRLNumber(object):
class TestSubjectAlternativeName(object):
def test_get_values_for_type(self):
- san = x509.SubjectAlternativeName(
- [x509.DNSName(u"cryptography.io")]
- )
+ san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
names = san.get_values_for_type(x509.DNSName)
assert names == [u"cryptography.io"]
def test_iter_names(self):
- san = x509.SubjectAlternativeName([
- x509.DNSName(u"cryptography.io"),
- x509.DNSName(u"crypto.local"),
- ])
+ san = x509.SubjectAlternativeName(
+ [x509.DNSName(u"cryptography.io"), x509.DNSName(u"crypto.local")]
+ )
assert len(san) == 2
assert list(san) == [
x509.DNSName(u"cryptography.io"),
@@ -2246,13 +2229,15 @@ class TestSubjectAlternativeName(object):
]
def test_indexing(self):
- san = x509.SubjectAlternativeName([
- x509.DNSName(u"cryptography.io"),
- x509.DNSName(u"crypto.local"),
- x509.DNSName(u"another.local"),
- x509.RFC822Name(u"email@another.local"),
- x509.UniformResourceIdentifier(u"http://another.local"),
- ])
+ san = x509.SubjectAlternativeName(
+ [
+ x509.DNSName(u"cryptography.io"),
+ x509.DNSName(u"crypto.local"),
+ x509.DNSName(u"another.local"),
+ x509.RFC822Name(u"email@another.local"),
+ x509.UniformResourceIdentifier(u"http://another.local"),
+ ]
+ )
assert san[-1] == san[4]
assert san[2:6:2] == [san[2], san[4]]
@@ -2263,11 +2248,7 @@ class TestSubjectAlternativeName(object):
)
def test_repr(self):
- san = x509.SubjectAlternativeName(
- [
- x509.DNSName(u"cryptography.io")
- ]
- )
+ san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
if not six.PY2:
assert repr(san) == (
"<SubjectAlternativeName("
@@ -2280,18 +2261,12 @@ class TestSubjectAlternativeName(object):
)
def test_eq(self):
- san = x509.SubjectAlternativeName(
- [x509.DNSName(u"cryptography.io")]
- )
- san2 = x509.SubjectAlternativeName(
- [x509.DNSName(u"cryptography.io")]
- )
+ san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
+ san2 = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
assert san == san2
def test_ne(self):
- san = x509.SubjectAlternativeName(
- [x509.DNSName(u"cryptography.io")]
- )
+ san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
san2 = x509.SubjectAlternativeName(
[x509.RFC822Name(u"admin@cryptography.io")]
)
@@ -2315,7 +2290,7 @@ class TestRSASubjectAlternativeNameExtension(object):
cert = _load_cert(
os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2332,7 +2307,7 @@ class TestRSASubjectAlternativeNameExtension(object):
cert = _load_cert(
os.path.join("x509", "wildcard_san.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2340,45 +2315,43 @@ class TestRSASubjectAlternativeNameExtension(object):
dns = ext.value.get_values_for_type(x509.DNSName)
assert dns == [
- u'*.langui.sh',
- u'langui.sh',
- u'*.saseliminator.com',
- u'saseliminator.com'
+ u"*.langui.sh",
+ u"langui.sh",
+ u"*.saseliminator.com",
+ u"saseliminator.com",
]
def test_san_empty_hostname(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_empty_hostname.pem"
- ),
+ os.path.join("x509", "custom", "san_empty_hostname.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
san = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
)
dns = san.value.get_values_for_type(x509.DNSName)
- assert dns == [u'']
+ assert dns == [u""]
def test_san_wildcard_idna_dns_name(self, backend):
cert = _load_cert(
os.path.join("x509", "custom", "san_wildcard_idna.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
)
dns = ext.value.get_values_for_type(x509.DNSName)
- assert dns == [u'*.xn--80ato2c.cryptography']
+ assert dns == [u"*.xn--80ato2c.cryptography"]
def test_unsupported_gn(self, backend):
cert = _load_cert(
os.path.join("x509", "san_x400address.der"),
x509.load_der_x509_certificate,
- backend
+ backend,
)
with pytest.raises(x509.UnsupportedGeneralNameType) as exc:
cert.extensions
@@ -2387,11 +2360,9 @@ class TestRSASubjectAlternativeNameExtension(object):
def test_registered_id(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_registered_id.pem"
- ),
+ os.path.join("x509", "custom", "san_registered_id.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2405,32 +2376,25 @@ class TestRSASubjectAlternativeNameExtension(object):
def test_uri(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_uri_with_port.pem"
- ),
+ os.path.join("x509", "custom", "san_uri_with_port.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
)
assert ext is not None
- uri = ext.value.get_values_for_type(
- x509.UniformResourceIdentifier
- )
+ uri = ext.value.get_values_for_type(x509.UniformResourceIdentifier)
assert uri == [
- u"gopher://xn--80ato2c.cryptography:70/path?q=s#hel"
- u"lo",
+ u"gopher://xn--80ato2c.cryptography:70/path?q=s#hel" u"lo",
u"http://someregulardomain.com",
]
def test_ipaddress(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_ipaddr.pem"
- ),
+ os.path.join("x509", "custom", "san_ipaddr.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2443,16 +2407,14 @@ class TestRSASubjectAlternativeNameExtension(object):
ip = san.get_values_for_type(x509.IPAddress)
assert [
ipaddress.ip_address(u"127.0.0.1"),
- ipaddress.ip_address(u"ff::")
+ ipaddress.ip_address(u"ff::"),
] == ip
def test_dirname(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_dirname.pem"
- ),
+ os.path.join("x509", "custom", "san_dirname.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2464,20 +2426,22 @@ class TestRSASubjectAlternativeNameExtension(object):
dirname = san.get_values_for_type(x509.DirectoryName)
assert [
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u'test'),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Org'),
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.COMMON_NAME, u"test"),
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org"),
+ x509.NameAttribute(
+ NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
+ ),
+ ]
+ )
] == dirname
def test_rfc822name(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_rfc822_idna.pem"
- ),
+ os.path.join("x509", "custom", "san_rfc822_idna.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2492,11 +2456,9 @@ class TestRSASubjectAlternativeNameExtension(object):
def test_idna2003_invalid(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_idna2003_dnsname.pem"
- ),
+ os.path.join("x509", "custom", "san_idna2003_dnsname.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
san = cert.extensions.get_extension_for_class(
x509.SubjectAlternativeName
@@ -2508,11 +2470,9 @@ class TestRSASubjectAlternativeNameExtension(object):
def test_unicode_rfc822_name_dns_name_uri(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_idna_names.pem"
- ),
+ os.path.join("x509", "custom", "san_idna_names.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2527,11 +2487,9 @@ class TestRSASubjectAlternativeNameExtension(object):
def test_rfc822name_dnsname_ipaddress_directoryname_uri(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_email_dns_ip_dirname_uri.pem"
- ),
+ os.path.join("x509", "custom", "san_email_dns_ip_dirname_uri.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
@@ -2550,42 +2508,43 @@ class TestRSASubjectAlternativeNameExtension(object):
assert [u"https://cryptography.io"] == uri
assert [u"cryptography.io"] == dns
assert [
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u'dirCN'),
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME, u'Cryptographic Authority'
- ),
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.COMMON_NAME, u"dirCN"),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME, u"Cryptographic Authority"
+ ),
+ ]
+ )
] == dirname
assert [
ipaddress.ip_address(u"127.0.0.1"),
- ipaddress.ip_address(u"ff::")
+ ipaddress.ip_address(u"ff::"),
] == ip
def test_invalid_rfc822name(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_rfc822_names.pem"
- ),
+ os.path.join("x509", "custom", "san_rfc822_names.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
san = cert.extensions.get_extension_for_class(
x509.SubjectAlternativeName
).value
values = san.get_values_for_type(x509.RFC822Name)
assert values == [
- u'email', u'email <email>', u'email <email@email>',
- u'email <email@xn--eml-vla4c.com>', u'myemail:'
+ u"email",
+ u"email <email>",
+ u"email <email@email>",
+ u"email <email@xn--eml-vla4c.com>",
+ u"myemail:",
]
def test_other_name(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "san_other_name.pem"
- ),
+ os.path.join("x509", "custom", "san_other_name.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
@@ -2594,8 +2553,9 @@ class TestRSASubjectAlternativeNameExtension(object):
assert ext is not None
assert ext.critical is False
- expected = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"),
- b'\x16\x0bHello World')
+ expected = x509.OtherName(
+ x509.ObjectIdentifier("1.2.3.4"), b"\x16\x0bHello World"
+ )
assert len(ext.value) == 1
assert list(ext.value)[0] == expected
@@ -2603,12 +2563,16 @@ class TestRSASubjectAlternativeNameExtension(object):
assert othernames == [expected]
def test_certbuilder(self, backend):
- sans = [u'*.example.org', u'*.xn--4ca7aey.example.com',
- u'foobar.example.net']
+ sans = [
+ u"*.example.org",
+ u"*.xn--4ca7aey.example.com",
+ u"foobar.example.net",
+ ]
private_key = RSA_KEY_2048.private_key(backend)
builder = _make_certbuilder(private_key)
builder = builder.add_extension(
- SubjectAlternativeName(list(map(DNSName, sans))), True)
+ SubjectAlternativeName(list(map(DNSName, sans))), True
+ )
cert = builder.sign(private_key, hashes.SHA1(), backend)
result = [
@@ -2625,11 +2589,9 @@ class TestRSASubjectAlternativeNameExtension(object):
class TestExtendedKeyUsageExtension(object):
def test_eku(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "extended_key_usage.pem"
- ),
+ os.path.join("x509", "custom", "extended_key_usage.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.EXTENDED_KEY_USAGE
@@ -2663,14 +2625,14 @@ class TestAccessDescription(object):
def test_valid_nonstandard_method(self):
ad = x509.AccessDescription(
ObjectIdentifier("2.999.1"),
- x509.UniformResourceIdentifier(u"http://example.com")
+ x509.UniformResourceIdentifier(u"http://example.com"),
)
assert ad is not None
def test_repr(self):
ad = x509.AccessDescription(
AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
)
if not six.PY2:
assert repr(ad) == (
@@ -2688,26 +2650,26 @@ class TestAccessDescription(object):
def test_eq(self):
ad = x509.AccessDescription(
AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
)
ad2 = x509.AccessDescription(
AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
)
assert ad == ad2
def test_ne(self):
ad = x509.AccessDescription(
AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
)
ad2 = x509.AccessDescription(
AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
)
ad3 = x509.AccessDescription(
AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://notthesame")
+ x509.UniformResourceIdentifier(u"http://notthesame"),
)
assert ad != ad2
assert ad != ad3
@@ -2716,15 +2678,15 @@ class TestAccessDescription(object):
def test_hash(self):
ad = x509.AccessDescription(
AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
)
ad2 = x509.AccessDescription(
AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
)
ad3 = x509.AccessDescription(
AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
)
assert hash(ad) == hash(ad2)
assert hash(ad) != hash(ad3)
@@ -2779,7 +2741,7 @@ class TestPolicyConstraintsExtension(object):
cert = _load_cert(
os.path.join("x509", "department-of-state-root.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.POLICY_CONSTRAINTS,
@@ -2787,21 +2749,23 @@ class TestPolicyConstraintsExtension(object):
assert ext.critical is True
assert ext.value == x509.PolicyConstraints(
- require_explicit_policy=None, inhibit_policy_mapping=0,
+ require_explicit_policy=None,
+ inhibit_policy_mapping=0,
)
def test_require_explicit_policy(self, backend):
cert = _load_cert(
os.path.join("x509", "custom", "policy_constraints_explicit.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.POLICY_CONSTRAINTS
)
assert ext.critical is True
assert ext.value == x509.PolicyConstraints(
- require_explicit_policy=1, inhibit_policy_mapping=None,
+ require_explicit_policy=1,
+ inhibit_policy_mapping=None,
)
@@ -2811,49 +2775,57 @@ class TestAuthorityInformationAccess(object):
x509.AuthorityInformationAccess(["notanAccessDescription"])
def test_iter_len(self):
- aia = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
- )
- ])
+ aia = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ ]
+ )
assert len(aia) == 2
assert list(aia) == [
x509.AccessDescription(
AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
),
x509.AccessDescription(
AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
- )
+ x509.UniformResourceIdentifier(u"http://domain.com/ca.crt"),
+ ),
]
def test_iter_input(self):
desc = [
x509.AccessDescription(
AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
)
]
aia = x509.AuthorityInformationAccess(iter(desc))
assert list(aia) == desc
def test_repr(self):
- aia = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
- )
- ])
+ aia = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ ]
+ )
if not six.PY2:
assert repr(aia) == (
"<AuthorityInformationAccess([<AccessDescription(access_method"
@@ -2876,108 +2848,354 @@ class TestAuthorityInformationAccess(object):
)
def test_eq(self):
- aia = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
- )
- ])
- aia2 = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
- )
- ])
+ aia = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ ]
+ )
+ aia2 = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ ]
+ )
assert aia == aia2
def test_ne(self):
- aia = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
- )
- ])
- aia2 = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- ])
+ aia = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ ]
+ )
+ aia2 = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ ]
+ )
assert aia != aia2
assert aia != object()
def test_indexing(self):
- aia = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp2.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp3.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp4.domain.com")
- ),
- ])
+ aia = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp2.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp3.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp4.domain.com"),
+ ),
+ ]
+ )
assert aia[-1] == aia[4]
assert aia[2:6:2] == [aia[2], aia[4]]
def test_hash(self):
- aia = x509.AuthorityInformationAccess([
+ aia = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ ]
+ )
+ aia2 = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ ]
+ )
+ aia3 = x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.other.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/ca.crt"
+ ),
+ ),
+ ]
+ )
+ assert hash(aia) == hash(aia2)
+ assert hash(aia) != hash(aia3)
+
+
+class TestSubjectInformationAccess(object):
+ def test_invalid_descriptions(self):
+ with pytest.raises(TypeError):
+ x509.SubjectInformationAccess(["notanAccessDescription"])
+
+ def test_iter_len(self):
+ sia = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+ ),
+ ]
+ )
+ assert len(sia) == 2
+ assert list(sia) == [
x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
),
x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
- )
- ])
- aia2 = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
),
+ ]
+
+ def test_iter_input(self):
+ desc = [
x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
)
- ])
- aia3 = x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.other.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
+ ]
+ sia = x509.SubjectInformationAccess(iter(desc))
+ assert list(sia) == desc
+
+ def test_repr(self):
+ sia = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ )
+ ]
+ )
+ if not six.PY2:
+ assert repr(sia) == (
+ "<SubjectInformationAccess([<AccessDescription(access_method"
+ "=<ObjectIdentifier(oid=1.3.6.1.5.5.7.48.5, name=caRepositor"
+ "y)>, access_location=<UniformResourceIdentifier(value='http"
+ "://ca.domain.com')>)>])>"
+ )
+ else:
+ assert repr(sia) == (
+ "<SubjectInformationAccess([<AccessDescription(access_method"
+ "=<ObjectIdentifier(oid=1.3.6.1.5.5.7.48.5, name=caRepositor"
+ "y)>, access_location=<UniformResourceIdentifier(value=u'htt"
+ "p://ca.domain.com')>)>])>"
)
- ])
- assert hash(aia) == hash(aia2)
- assert hash(aia) != hash(aia3)
+
+ def test_eq(self):
+ sia = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+ ),
+ ]
+ )
+ sia2 = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+ ),
+ ]
+ )
+ assert sia == sia2
+
+ def test_ne(self):
+ sia = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+ ),
+ ]
+ )
+ sia2 = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ ]
+ )
+
+ assert sia != sia2
+ assert sia != object()
+
+ def test_indexing(self):
+ sia = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca3.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca4.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca5.domain.com"),
+ ),
+ ]
+ )
+ assert sia[-1] == sia[4]
+ assert sia[2:6:2] == [sia[2], sia[4]]
+
+ def test_hash(self):
+ sia = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+ ),
+ ]
+ )
+ sia2 = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca2.domain.com"),
+ ),
+ ]
+ )
+ sia3 = x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca.domain.com"),
+ ),
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"http://ca3.domain.com"),
+ ),
+ ]
+ )
+ assert hash(sia) == hash(sia2)
+ assert hash(sia) != hash(sia3)
+
+
+@pytest.mark.requires_backend_interface(interface=RSABackend)
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestSubjectInformationAccessExtension(object):
+ def test_sia(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "custom", "sia.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ ext = cert.extensions.get_extension_for_oid(
+ ExtensionOID.SUBJECT_INFORMATION_ACCESS
+ )
+ assert ext is not None
+ assert ext.critical is False
+
+ assert ext.value == x509.SubjectInformationAccess(
+ [
+ x509.AccessDescription(
+ SubjectInformationAccessOID.CA_REPOSITORY,
+ x509.UniformResourceIdentifier(u"https://my.ca.issuer/"),
+ ),
+ x509.AccessDescription(
+ x509.ObjectIdentifier("2.999.7"),
+ x509.UniformResourceIdentifier(
+ u"gopher://info-mac-archive"
+ ),
+ ),
+ ]
+ )
@pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -2987,7 +3205,7 @@ class TestAuthorityInformationAccessExtension(object):
cert = _load_cert(
os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.AUTHORITY_INFORMATION_ACCESS
@@ -2995,22 +3213,26 @@ class TestAuthorityInformationAccessExtension(object):
assert ext is not None
assert ext.critical is False
- assert ext.value == x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://gv.symcd.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.UniformResourceIdentifier(u"http://gv.symcb.com/gv.crt")
- ),
- ])
+ assert ext.value == x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://gv.symcd.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.UniformResourceIdentifier(
+ u"http://gv.symcb.com/gv.crt"
+ ),
+ ),
+ ]
+ )
def test_aia_multiple_ocsp_ca_issuers(self, backend):
cert = _load_cert(
os.path.join("x509", "custom", "aia_ocsp_ca_issuers.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.AUTHORITY_INFORMATION_ACCESS
@@ -3018,30 +3240,39 @@ class TestAuthorityInformationAccessExtension(object):
assert ext is not None
assert ext.critical is False
- assert ext.value == x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp2.domain.com")
- ),
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.DirectoryName(x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"myCN"),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME,
- u"some Org"),
- ]))
- ),
- ])
+ assert ext.value == x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp2.domain.com"),
+ ),
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"myCN"
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME, u"some Org"
+ ),
+ ]
+ )
+ ),
+ ),
+ ]
+ )
def test_aia_ocsp_only(self, backend):
cert = _load_cert(
os.path.join("x509", "custom", "aia_ocsp.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.AUTHORITY_INFORMATION_ACCESS
@@ -3049,18 +3280,20 @@ class TestAuthorityInformationAccessExtension(object):
assert ext is not None
assert ext.critical is False
- assert ext.value == x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.OCSP,
- x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
- ),
- ])
+ assert ext.value == x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.OCSP,
+ x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
+ ),
+ ]
+ )
def test_aia_ca_issuers_only(self, backend):
cert = _load_cert(
os.path.join("x509", "custom", "aia_ca_issuers.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.AUTHORITY_INFORMATION_ACCESS
@@ -3068,16 +3301,25 @@ class TestAuthorityInformationAccessExtension(object):
assert ext is not None
assert ext.critical is False
- assert ext.value == x509.AuthorityInformationAccess([
- x509.AccessDescription(
- AuthorityInformationAccessOID.CA_ISSUERS,
- x509.DirectoryName(x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"myCN"),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME,
- u"some Org"),
- ]))
- ),
- ])
+ assert ext.value == x509.AuthorityInformationAccess(
+ [
+ x509.AccessDescription(
+ AuthorityInformationAccessOID.CA_ISSUERS,
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"myCN"
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME, u"some Org"
+ ),
+ ]
+ )
+ ),
+ ),
+ ]
+ )
@pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -3085,11 +3327,9 @@ class TestAuthorityInformationAccessExtension(object):
class TestAuthorityKeyIdentifierExtension(object):
def test_aki_keyid(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "cryptography.io.pem"
- ),
+ os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.AUTHORITY_KEY_IDENTIFIER
@@ -3105,11 +3345,9 @@ class TestAuthorityKeyIdentifierExtension(object):
def test_aki_all_fields(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "authority_key_identifier.pem"
- ),
+ os.path.join("x509", "custom", "authority_key_identifier.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.AUTHORITY_KEY_IDENTIFIER
@@ -3122,14 +3360,14 @@ class TestAuthorityKeyIdentifierExtension(object):
)
assert ext.value.authority_cert_issuer == [
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME, u"PyCA"
- ),
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"cryptography.io"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io"
+ ),
+ ]
+ )
)
]
assert ext.value.authority_cert_serial_number == 3
@@ -3140,7 +3378,7 @@ class TestAuthorityKeyIdentifierExtension(object):
"x509", "custom", "authority_key_identifier_no_keyid.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.AUTHORITY_KEY_IDENTIFIER
@@ -3151,14 +3389,14 @@ class TestAuthorityKeyIdentifierExtension(object):
assert ext.value.key_identifier is None
assert ext.value.authority_cert_issuer == [
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME, u"PyCA"
- ),
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"cryptography.io"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io"
+ ),
+ ]
+ )
)
]
assert ext.value.authority_cert_serial_number == 3
@@ -3167,12 +3405,12 @@ class TestAuthorityKeyIdentifierExtension(object):
issuer_cert = _load_cert(
os.path.join("x509", "rapidssl_sha256_ca_g3.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cert = _load_cert(
os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.AUTHORITY_KEY_IDENTIFIER
@@ -3186,21 +3424,21 @@ class TestAuthorityKeyIdentifierExtension(object):
issuer_cert = _load_cert(
os.path.join("x509", "rapidssl_sha256_ca_g3.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cert = _load_cert(
os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
ext = cert.extensions.get_extension_for_oid(
ExtensionOID.AUTHORITY_KEY_IDENTIFIER
)
- ski = issuer_cert.extensions.get_extension_for_class(
+ ski_ext = issuer_cert.extensions.get_extension_for_class(
x509.SubjectKeyIdentifier
)
aki = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
- ski
+ ski_ext.value
)
assert ext.value == aki
@@ -3212,7 +3450,7 @@ class TestNameConstraints(object):
permitted_subtrees=[
x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
],
- excluded_subtrees=None
+ excluded_subtrees=None,
)
with pytest.raises(TypeError):
@@ -3220,15 +3458,14 @@ class TestNameConstraints(object):
permitted_subtrees=None,
excluded_subtrees=[
x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
- ]
+ ],
)
def test_ipaddress_allowed_type(self):
permitted = [x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/29"))]
excluded = [x509.IPAddress(ipaddress.IPv4Network(u"10.10.0.0/24"))]
nc = x509.NameConstraints(
- permitted_subtrees=permitted,
- excluded_subtrees=excluded
+ permitted_subtrees=permitted, excluded_subtrees=excluded
)
assert nc.permitted_subtrees == permitted
assert nc.excluded_subtrees == excluded
@@ -3270,8 +3507,7 @@ class TestNameConstraints(object):
def test_repr(self):
permitted = [x509.DNSName(u"name.local"), x509.DNSName(u"name2.local")]
nc = x509.NameConstraints(
- permitted_subtrees=permitted,
- excluded_subtrees=None
+ permitted_subtrees=permitted, excluded_subtrees=None
)
if not six.PY2:
assert repr(nc) == (
@@ -3289,26 +3525,26 @@ class TestNameConstraints(object):
def test_eq(self):
nc = x509.NameConstraints(
permitted_subtrees=[x509.DNSName(u"name.local")],
- excluded_subtrees=[x509.DNSName(u"name2.local")]
+ excluded_subtrees=[x509.DNSName(u"name2.local")],
)
nc2 = x509.NameConstraints(
permitted_subtrees=[x509.DNSName(u"name.local")],
- excluded_subtrees=[x509.DNSName(u"name2.local")]
+ excluded_subtrees=[x509.DNSName(u"name2.local")],
)
assert nc == nc2
def test_ne(self):
nc = x509.NameConstraints(
permitted_subtrees=[x509.DNSName(u"name.local")],
- excluded_subtrees=[x509.DNSName(u"name2.local")]
+ excluded_subtrees=[x509.DNSName(u"name2.local")],
)
nc2 = x509.NameConstraints(
permitted_subtrees=[x509.DNSName(u"name.local")],
- excluded_subtrees=None
+ excluded_subtrees=None,
)
nc3 = x509.NameConstraints(
permitted_subtrees=None,
- excluded_subtrees=[x509.DNSName(u"name2.local")]
+ excluded_subtrees=[x509.DNSName(u"name2.local")],
)
assert nc != nc2
@@ -3318,19 +3554,19 @@ class TestNameConstraints(object):
def test_hash(self):
nc = x509.NameConstraints(
permitted_subtrees=[x509.DNSName(u"name.local")],
- excluded_subtrees=[x509.DNSName(u"name2.local")]
+ excluded_subtrees=[x509.DNSName(u"name2.local")],
)
nc2 = x509.NameConstraints(
permitted_subtrees=[x509.DNSName(u"name.local")],
- excluded_subtrees=[x509.DNSName(u"name2.local")]
+ excluded_subtrees=[x509.DNSName(u"name2.local")],
)
nc3 = x509.NameConstraints(
permitted_subtrees=[x509.DNSName(u"name.local")],
- excluded_subtrees=None
+ excluded_subtrees=None,
)
nc4 = x509.NameConstraints(
permitted_subtrees=None,
- excluded_subtrees=[x509.DNSName(u"name.local")]
+ excluded_subtrees=[x509.DNSName(u"name.local")],
)
assert hash(nc) == hash(nc2)
assert hash(nc) != hash(nc3)
@@ -3342,51 +3578,43 @@ class TestNameConstraints(object):
class TestNameConstraintsExtension(object):
def test_permitted_excluded(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "nc_permitted_excluded_2.pem"
- ),
+ os.path.join("x509", "custom", "nc_permitted_excluded_2.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
nc = cert.extensions.get_extension_for_oid(
ExtensionOID.NAME_CONSTRAINTS
).value
assert nc == x509.NameConstraints(
- permitted_subtrees=[
- x509.DNSName(u"zombo.local"),
- ],
+ permitted_subtrees=[x509.DNSName(u"zombo.local")],
excluded_subtrees=[
- x509.DirectoryName(x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"zombo")
- ]))
- ]
+ x509.DirectoryName(
+ x509.Name(
+ [x509.NameAttribute(NameOID.COMMON_NAME, u"zombo")]
+ )
+ )
+ ],
)
def test_permitted(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "nc_permitted_2.pem"
- ),
+ os.path.join("x509", "custom", "nc_permitted_2.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
nc = cert.extensions.get_extension_for_oid(
ExtensionOID.NAME_CONSTRAINTS
).value
assert nc == x509.NameConstraints(
- permitted_subtrees=[
- x509.DNSName(u"zombo.local"),
- ],
- excluded_subtrees=None
+ permitted_subtrees=[x509.DNSName(u"zombo.local")],
+ excluded_subtrees=None,
)
def test_permitted_with_leading_period(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "nc_permitted.pem"
- ),
+ os.path.join("x509", "custom", "nc_permitted.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
nc = cert.extensions.get_extension_for_oid(
ExtensionOID.NAME_CONSTRAINTS
@@ -3394,18 +3622,16 @@ class TestNameConstraintsExtension(object):
assert nc == x509.NameConstraints(
permitted_subtrees=[
x509.DNSName(u".cryptography.io"),
- x509.UniformResourceIdentifier(u"ftp://cryptography.test")
+ x509.UniformResourceIdentifier(u"ftp://cryptography.test"),
],
- excluded_subtrees=None
+ excluded_subtrees=None,
)
def test_excluded_with_leading_period(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "nc_excluded.pem"
- ),
+ os.path.join("x509", "custom", "nc_excluded.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
nc = cert.extensions.get_extension_for_oid(
ExtensionOID.NAME_CONSTRAINTS
@@ -3414,17 +3640,15 @@ class TestNameConstraintsExtension(object):
permitted_subtrees=None,
excluded_subtrees=[
x509.DNSName(u".cryptography.io"),
- x509.UniformResourceIdentifier(u"gopher://cryptography.test")
- ]
+ x509.UniformResourceIdentifier(u"gopher://cryptography.test"),
+ ],
)
def test_permitted_excluded_with_ips(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "nc_permitted_excluded.pem"
- ),
+ os.path.join("x509", "custom", "nc_permitted_excluded.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
nc = cert.extensions.get_extension_for_oid(
ExtensionOID.NAME_CONSTRAINTS
@@ -3437,16 +3661,14 @@ class TestNameConstraintsExtension(object):
excluded_subtrees=[
x509.DNSName(u".domain.com"),
x509.UniformResourceIdentifier(u"http://test.local"),
- ]
+ ],
)
def test_single_ip_netmask(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "nc_single_ip_netmask.pem"
- ),
+ os.path.join("x509", "custom", "nc_single_ip_netmask.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
nc = cert.extensions.get_extension_for_oid(
ExtensionOID.NAME_CONSTRAINTS
@@ -3456,16 +3678,14 @@ class TestNameConstraintsExtension(object):
x509.IPAddress(ipaddress.IPv6Network(u"FF:0:0:0:0:0:0:0/128")),
x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.1/32")),
],
- excluded_subtrees=None
+ excluded_subtrees=None,
)
def test_invalid_netmask(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "nc_invalid_ip_netmask.pem"
- ),
+ os.path.join("x509", "custom", "nc_invalid_ip_netmask.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
with pytest.raises(ValueError):
cert.extensions.get_extension_for_oid(
@@ -3473,13 +3693,20 @@ class TestNameConstraintsExtension(object):
)
def test_certbuilder(self, backend):
- permitted = [u'.example.org', u'.xn--4ca7aey.example.com',
- u'foobar.example.net']
+ permitted = [
+ u".example.org",
+ u".xn--4ca7aey.example.com",
+ u"foobar.example.net",
+ ]
private_key = RSA_KEY_2048.private_key(backend)
builder = _make_certbuilder(private_key)
builder = builder.add_extension(
- NameConstraints(permitted_subtrees=list(map(DNSName, permitted)),
- excluded_subtrees=[]), True)
+ NameConstraints(
+ permitted_subtrees=list(map(DNSName, permitted)),
+ excluded_subtrees=[],
+ ),
+ True,
+ )
cert = builder.sign(private_key, hashes.SHA1(), backend)
result = [
@@ -3514,7 +3741,7 @@ class TestDistributionPoint(object):
[x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
None,
frozenset(["notreasonflags"]),
- None
+ None,
)
def test_reason_not_frozenset(self):
@@ -3523,7 +3750,7 @@ class TestDistributionPoint(object):
[x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
None,
[x509.ReasonFlags.ca_compromise],
- None
+ None,
)
def test_disallowed_reasons(self):
@@ -3532,7 +3759,7 @@ class TestDistributionPoint(object):
[x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
None,
frozenset([x509.ReasonFlags.unspecified]),
- None
+ None,
)
with pytest.raises(ValueError):
@@ -3540,16 +3767,13 @@ class TestDistributionPoint(object):
[x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
None,
frozenset([x509.ReasonFlags.remove_from_crl]),
- None
+ None,
)
def test_reason_only(self):
with pytest.raises(ValueError):
x509.DistributionPoint(
- None,
- None,
- frozenset([x509.ReasonFlags.aa_compromise]),
- None
+ None, None, frozenset([x509.ReasonFlags.aa_compromise]), None
)
def test_eq(self):
@@ -3559,11 +3783,13 @@ class TestDistributionPoint(object):
frozenset([x509.ReasonFlags.superseded]),
[
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"Important CA"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"Important CA"
+ )
+ ]
+ )
)
],
)
@@ -3573,11 +3799,13 @@ class TestDistributionPoint(object):
frozenset([x509.ReasonFlags.superseded]),
[
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"Important CA"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"Important CA"
+ )
+ ]
+ )
)
],
)
@@ -3590,11 +3818,13 @@ class TestDistributionPoint(object):
frozenset([x509.ReasonFlags.superseded]),
[
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"Important CA"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"Important CA"
+ )
+ ]
+ )
)
],
)
@@ -3602,7 +3832,7 @@ class TestDistributionPoint(object):
[x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
None,
None,
- None
+ None,
)
assert dp != dp2
assert dp != object()
@@ -3611,9 +3841,9 @@ class TestDistributionPoint(object):
name = [x509.UniformResourceIdentifier(u"http://crypt.og/crl")]
issuer = [
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"Important CA")
- ])
+ x509.Name(
+ [x509.NameAttribute(NameOID.COMMON_NAME, u"Important CA")]
+ )
)
]
dp = x509.DistributionPoint(
@@ -3628,17 +3858,19 @@ class TestDistributionPoint(object):
def test_repr(self):
dp = x509.DistributionPoint(
None,
- x509.RelativeDistinguishedName([
- x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")
- ]),
+ x509.RelativeDistinguishedName(
+ [x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")]
+ ),
frozenset([x509.ReasonFlags.ca_compromise]),
[
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"Important CA"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"Important CA"
+ )
+ ]
+ )
)
],
)
@@ -3664,11 +3896,13 @@ class TestDistributionPoint(object):
frozenset([x509.ReasonFlags.superseded]),
[
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"Important CA"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"Important CA"
+ )
+ ]
+ )
)
],
)
@@ -3678,19 +3912,21 @@ class TestDistributionPoint(object):
frozenset([x509.ReasonFlags.superseded]),
[
x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"Important CA"
- )
- ])
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"Important CA"
+ )
+ ]
+ )
)
],
)
dp3 = x509.DistributionPoint(
None,
- x509.RelativeDistinguishedName([
- x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")
- ]),
+ x509.RelativeDistinguishedName(
+ [x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")]
+ ),
None,
None,
)
@@ -3704,17 +3940,23 @@ class TestFreshestCRL(object):
x509.FreshestCRL(["notadistributionpoint"])
def test_iter_len(self):
- fcrl = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"http://domain")],
- None, None, None
- ),
- ])
+ fcrl = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"http://domain")],
+ None,
+ None,
+ None,
+ ),
+ ]
+ )
assert len(fcrl) == 1
assert list(fcrl) == [
x509.DistributionPoint(
[x509.UniformResourceIdentifier(u"http://domain")],
- None, None, None
+ None,
+ None,
+ None,
),
]
@@ -3722,21 +3964,25 @@ class TestFreshestCRL(object):
points = [
x509.DistributionPoint(
[x509.UniformResourceIdentifier(u"http://domain")],
- None, None, None
+ None,
+ None,
+ None,
),
]
fcrl = x509.FreshestCRL(iter(points))
assert list(fcrl) == points
def test_repr(self):
- fcrl = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([x509.ReasonFlags.key_compromise]),
- None
- ),
- ])
+ fcrl = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset([x509.ReasonFlags.key_compromise]),
+ None,
+ ),
+ ]
+ )
if not six.PY2:
assert repr(fcrl) == (
"<FreshestCRL([<DistributionPoint(full_name=[<Unifo"
@@ -3753,134 +3999,178 @@ class TestFreshestCRL(object):
)
def test_eq(self):
- fcrl = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- fcrl2 = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
+ fcrl = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ fcrl2 = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
assert fcrl == fcrl2
def test_ne(self):
- fcrl = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- fcrl2 = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain2")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- fcrl3 = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([x509.ReasonFlags.key_compromise]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- fcrl4 = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing2")],
- ),
- ])
+ fcrl = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ fcrl2 = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain2")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ fcrl3 = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset([x509.ReasonFlags.key_compromise]),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ fcrl4 = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing2")],
+ ),
+ ]
+ )
assert fcrl != fcrl2
assert fcrl != fcrl3
assert fcrl != fcrl4
assert fcrl != object()
def test_hash(self):
- fcrl = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- fcrl2 = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- fcrl3 = x509.FreshestCRL([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([x509.ReasonFlags.key_compromise]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
+ fcrl = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ fcrl2 = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ fcrl3 = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset([x509.ReasonFlags.key_compromise]),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
assert hash(fcrl) == hash(fcrl2)
assert hash(fcrl) != hash(fcrl3)
def test_indexing(self):
- fcrl = x509.FreshestCRL([
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing2")],
- ),
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing3")],
- ),
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing4")],
- ),
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing5")],
- ),
- ])
+ fcrl = x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing2")],
+ ),
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing3")],
+ ),
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing4")],
+ ),
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing5")],
+ ),
+ ]
+ )
assert fcrl[-1] == fcrl[4]
assert fcrl[2:6:2] == [fcrl[2], fcrl[4]]
@@ -3891,39 +4181,45 @@ class TestCRLDistributionPoints(object):
x509.CRLDistributionPoints(["notadistributionpoint"])
def test_iter_len(self):
- cdp = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"http://domain")],
- None,
- None,
- None
- ),
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- None
- ),
- ])
+ cdp = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"http://domain")],
+ None,
+ None,
+ None,
+ ),
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ None,
+ ),
+ ]
+ )
assert len(cdp) == 2
assert list(cdp) == [
x509.DistributionPoint(
[x509.UniformResourceIdentifier(u"http://domain")],
None,
None,
- None
+ None,
),
x509.DistributionPoint(
[x509.UniformResourceIdentifier(u"ftp://domain")],
None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- None
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ None,
),
]
@@ -3933,21 +4229,23 @@ class TestCRLDistributionPoints(object):
[x509.UniformResourceIdentifier(u"http://domain")],
None,
None,
- None
+ None,
),
]
cdp = x509.CRLDistributionPoints(iter(points))
assert list(cdp) == points
def test_repr(self):
- cdp = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([x509.ReasonFlags.key_compromise]),
- None
- ),
- ])
+ cdp = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset([x509.ReasonFlags.key_compromise]),
+ None,
+ ),
+ ]
+ )
if not six.PY2:
assert repr(cdp) == (
"<CRLDistributionPoints([<DistributionPoint(full_name=[<Unifo"
@@ -3964,134 +4262,178 @@ class TestCRLDistributionPoints(object):
)
def test_eq(self):
- cdp = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- cdp2 = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
+ cdp = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ cdp2 = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
assert cdp == cdp2
def test_ne(self):
- cdp = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- cdp2 = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain2")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- cdp3 = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([x509.ReasonFlags.key_compromise]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- cdp4 = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing2")],
- ),
- ])
+ cdp = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ cdp2 = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain2")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ cdp3 = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset([x509.ReasonFlags.key_compromise]),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ cdp4 = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing2")],
+ ),
+ ]
+ )
assert cdp != cdp2
assert cdp != cdp3
assert cdp != cdp4
assert cdp != object()
def test_hash(self):
- cdp = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- cdp2 = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- ]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
- cdp3 = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- [x509.UniformResourceIdentifier(u"ftp://domain")],
- None,
- frozenset([x509.ReasonFlags.key_compromise]),
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- ])
+ cdp = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ cdp2 = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
+ cdp3 = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ [x509.UniformResourceIdentifier(u"ftp://domain")],
+ None,
+ frozenset([x509.ReasonFlags.key_compromise]),
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ ]
+ )
assert hash(cdp) == hash(cdp2)
assert hash(cdp) != hash(cdp3)
def test_indexing(self):
- ci = x509.CRLDistributionPoints([
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing")],
- ),
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing2")],
- ),
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing3")],
- ),
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing4")],
- ),
- x509.DistributionPoint(
- None, None, None,
- [x509.UniformResourceIdentifier(u"uri://thing5")],
- ),
- ])
+ ci = x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing")],
+ ),
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing2")],
+ ),
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing3")],
+ ),
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing4")],
+ ),
+ x509.DistributionPoint(
+ None,
+ None,
+ None,
+ [x509.UniformResourceIdentifier(u"uri://thing5")],
+ ),
+ ]
+ )
assert ci[-1] == ci[4]
assert ci[2:6:2] == [ci[2], ci[4]]
@@ -4105,49 +4447,63 @@ class TestCRLDistributionPointsExtension(object):
"x509", "PKITS_data", "certs", "ValidcRLIssuerTest28EE.crt"
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
cdps = cert.extensions.get_extension_for_oid(
ExtensionOID.CRL_DISTRIBUTION_POINTS
).value
- assert cdps == x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME,
- u"Test Certificates 2011"
- ),
- x509.NameAttribute(
- NameOID.ORGANIZATIONAL_UNIT_NAME,
- u"indirectCRL CA3 cRLIssuer"
- ),
- x509.NameAttribute(
- NameOID.COMMON_NAME,
- u"indirect CRL for indirectCRL CA3"
- ),
- ])
- )],
- relative_name=None,
- reasons=None,
- crl_issuer=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME,
- u"Test Certificates 2011"
- ),
- x509.NameAttribute(
- NameOID.ORGANIZATIONAL_UNIT_NAME,
- u"indirectCRL CA3 cRLIssuer"
- ),
- ])
- )],
- )
- ])
+ assert cdps == x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME,
+ u"Test Certificates 2011",
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATIONAL_UNIT_NAME,
+ u"indirectCRL CA3 cRLIssuer",
+ ),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"indirect CRL for indirectCRL CA3",
+ ),
+ ]
+ )
+ )
+ ],
+ relative_name=None,
+ reasons=None,
+ crl_issuer=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME,
+ u"Test Certificates 2011",
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATIONAL_UNIT_NAME,
+ u"indirectCRL CA3 cRLIssuer",
+ ),
+ ]
+ )
+ )
+ ],
+ )
+ ]
+ )
def test_relativename_and_crl_issuer(self, backend):
cert = _load_cert(
@@ -4155,38 +4511,48 @@ class TestCRLDistributionPointsExtension(object):
"x509", "PKITS_data", "certs", "ValidcRLIssuerTest29EE.crt"
),
x509.load_der_x509_certificate,
- backend
+ backend,
)
cdps = cert.extensions.get_extension_for_oid(
ExtensionOID.CRL_DISTRIBUTION_POINTS
).value
- assert cdps == x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- NameOID.COMMON_NAME,
- u"indirect CRL for indirectCRL CA3"
+ assert cdps == x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=None,
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME,
+ u"indirect CRL for indirectCRL CA3",
+ ),
+ ]
),
- ]),
- reasons=None,
- crl_issuer=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME,
- u"Test Certificates 2011"
- ),
- x509.NameAttribute(
- NameOID.ORGANIZATIONAL_UNIT_NAME,
- u"indirectCRL CA3 cRLIssuer"
- ),
- ])
- )],
- )
- ])
+ reasons=None,
+ crl_issuer=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME,
+ u"Test Certificates 2011",
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATIONAL_UNIT_NAME,
+ u"indirectCRL CA3 cRLIssuer",
+ ),
+ ]
+ )
+ )
+ ],
+ )
+ ]
+ )
def test_fullname_crl_issuer_reasons(self, backend):
cert = _load_cert(
@@ -4194,145 +4560,169 @@ class TestCRLDistributionPointsExtension(object):
"x509", "custom", "cdp_fullname_reasons_crl_issuer.pem"
),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cdps = cert.extensions.get_extension_for_oid(
ExtensionOID.CRL_DISTRIBUTION_POINTS
).value
- assert cdps == x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=[x509.UniformResourceIdentifier(
- u"http://myhost.com/myca.crl"
- )],
- relative_name=None,
- reasons=frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise
- ]),
- crl_issuer=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- x509.NameAttribute(
- NameOID.ORGANIZATION_NAME, u"PyCA"
- ),
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"cryptography CA"
- ),
- ])
- )],
- )
- ])
+ assert cdps == x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"http://myhost.com/myca.crl"
+ )
+ ],
+ relative_name=None,
+ reasons=frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ ]
+ ),
+ crl_issuer=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.ORGANIZATION_NAME, u"PyCA"
+ ),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography CA"
+ ),
+ ]
+ )
+ )
+ ],
+ )
+ ]
+ )
def test_all_reasons(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "cdp_all_reasons.pem"
- ),
+ os.path.join("x509", "custom", "cdp_all_reasons.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cdps = cert.extensions.get_extension_for_oid(
ExtensionOID.CRL_DISTRIBUTION_POINTS
).value
- assert cdps == x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=[x509.UniformResourceIdentifier(
- u"http://domain.com/some.crl"
- )],
- relative_name=None,
- reasons=frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- x509.ReasonFlags.affiliation_changed,
- x509.ReasonFlags.superseded,
- x509.ReasonFlags.privilege_withdrawn,
- x509.ReasonFlags.cessation_of_operation,
- x509.ReasonFlags.aa_compromise,
- x509.ReasonFlags.certificate_hold,
- ]),
- crl_issuer=None
- )
- ])
+ assert cdps == x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/some.crl"
+ )
+ ],
+ relative_name=None,
+ reasons=frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ x509.ReasonFlags.affiliation_changed,
+ x509.ReasonFlags.superseded,
+ x509.ReasonFlags.privilege_withdrawn,
+ x509.ReasonFlags.cessation_of_operation,
+ x509.ReasonFlags.aa_compromise,
+ x509.ReasonFlags.certificate_hold,
+ ]
+ ),
+ crl_issuer=None,
+ )
+ ]
+ )
def test_single_reason(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "cdp_reason_aa_compromise.pem"
- ),
+ os.path.join("x509", "custom", "cdp_reason_aa_compromise.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cdps = cert.extensions.get_extension_for_oid(
ExtensionOID.CRL_DISTRIBUTION_POINTS
).value
- assert cdps == x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=[x509.UniformResourceIdentifier(
- u"http://domain.com/some.crl"
- )],
- relative_name=None,
- reasons=frozenset([x509.ReasonFlags.aa_compromise]),
- crl_issuer=None
- )
- ])
+ assert cdps == x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"http://domain.com/some.crl"
+ )
+ ],
+ relative_name=None,
+ reasons=frozenset([x509.ReasonFlags.aa_compromise]),
+ crl_issuer=None,
+ )
+ ]
+ )
def test_crl_issuer_only(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "cdp_crl_issuer.pem"
- ),
+ os.path.join("x509", "custom", "cdp_crl_issuer.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cdps = cert.extensions.get_extension_for_oid(
ExtensionOID.CRL_DISTRIBUTION_POINTS
).value
- assert cdps == x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=None,
- relative_name=None,
- reasons=None,
- crl_issuer=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"cryptography CA"
- ),
- ])
- )],
- )
- ])
+ assert cdps == x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=None,
+ relative_name=None,
+ reasons=None,
+ crl_issuer=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography CA"
+ ),
+ ]
+ )
+ )
+ ],
+ )
+ ]
+ )
def test_crl_empty_hostname(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "cdp_empty_hostname.pem"
- ),
+ os.path.join("x509", "custom", "cdp_empty_hostname.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
cdps = cert.extensions.get_extension_for_oid(
ExtensionOID.CRL_DISTRIBUTION_POINTS
).value
- assert cdps == x509.CRLDistributionPoints([
- x509.DistributionPoint(
- full_name=[x509.UniformResourceIdentifier(
- u"ldap:///CN=A,OU=B,dc=C,DC=D?E?F?G?H=I"
- )],
- relative_name=None,
- reasons=None,
- crl_issuer=None
- )
- ])
+ assert cdps == x509.CRLDistributionPoints(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"ldap:///CN=A,OU=B,dc=C,DC=D?E?F?G?H=I"
+ )
+ ],
+ relative_name=None,
+ reasons=None,
+ crl_issuer=None,
+ )
+ ]
+ )
@pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -4340,39 +4730,47 @@ class TestCRLDistributionPointsExtension(object):
class TestFreshestCRLExtension(object):
def test_vector(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "freshestcrl.pem"
- ),
+ os.path.join("x509", "custom", "freshestcrl.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
fcrl = cert.extensions.get_extension_for_class(x509.FreshestCRL).value
- assert fcrl == x509.FreshestCRL([
- x509.DistributionPoint(
- full_name=[
- x509.UniformResourceIdentifier(
- u'http://myhost.com/myca.crl'
- ),
- x509.UniformResourceIdentifier(
- u'http://backup.myhost.com/myca.crl'
- )
- ],
- relative_name=None,
- reasons=frozenset([
- x509.ReasonFlags.ca_compromise,
- x509.ReasonFlags.key_compromise
- ]),
- crl_issuer=[x509.DirectoryName(
- x509.Name([
- x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
- x509.NameAttribute(
- NameOID.COMMON_NAME, u"cryptography CA"
+ assert fcrl == x509.FreshestCRL(
+ [
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"http://myhost.com/myca.crl"
),
- ])
- )]
- )
- ])
+ x509.UniformResourceIdentifier(
+ u"http://backup.myhost.com/myca.crl"
+ ),
+ ],
+ relative_name=None,
+ reasons=frozenset(
+ [
+ x509.ReasonFlags.ca_compromise,
+ x509.ReasonFlags.key_compromise,
+ ]
+ ),
+ crl_issuer=[
+ x509.DirectoryName(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COUNTRY_NAME, u"US"
+ ),
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography CA"
+ ),
+ ]
+ )
+ )
+ ],
+ )
+ ]
+ )
@pytest.mark.requires_backend_interface(interface=RSABackend)
@@ -4380,17 +4778,38 @@ class TestFreshestCRLExtension(object):
class TestOCSPNoCheckExtension(object):
def test_nocheck(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "ocsp_nocheck.pem"
- ),
+ os.path.join("x509", "custom", "ocsp_nocheck.pem"),
x509.load_pem_x509_certificate,
- backend
- )
- ext = cert.extensions.get_extension_for_oid(
- ExtensionOID.OCSP_NO_CHECK
+ backend,
)
+ ext = cert.extensions.get_extension_for_oid(ExtensionOID.OCSP_NO_CHECK)
assert isinstance(ext.value, x509.OCSPNoCheck)
+ def test_eq(self):
+ onc1 = x509.OCSPNoCheck()
+ onc2 = x509.OCSPNoCheck()
+
+ assert onc1 == onc2
+
+ def test_hash(self):
+ onc1 = x509.OCSPNoCheck()
+ onc2 = x509.OCSPNoCheck()
+
+ assert hash(onc1) == hash(onc2)
+
+ def test_ne(self):
+ onc1 = x509.OCSPNoCheck()
+ onc2 = x509.OCSPNoCheck()
+
+ assert onc1 == onc2
+ assert (onc1 != onc2) is False
+ assert onc1 != object()
+
+ def test_repr(self):
+ onc = x509.OCSPNoCheck()
+
+ assert repr(onc) == "<OCSPNoCheck()>"
+
class TestInhibitAnyPolicy(object):
def test_not_int(self):
@@ -4429,11 +4848,9 @@ class TestInhibitAnyPolicy(object):
class TestInhibitAnyPolicyExtension(object):
def test_inhibit_any_policy(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "inhibit_any_policy_5.pem"
- ),
+ os.path.join("x509", "custom", "inhibit_any_policy_5.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
iap = cert.extensions.get_extension_for_oid(
ExtensionOID.INHIBIT_ANY_POLICY
@@ -4450,7 +4867,8 @@ class TestIssuingDistributionPointExtension(object):
x509.IssuingDistributionPoint(
full_name=[
x509.UniformResourceIdentifier(
- u"http://myhost.com/myca.crl")
+ u"http://myhost.com/myca.crl"
+ )
],
relative_name=None,
only_contains_user_certs=False,
@@ -4458,14 +4876,15 @@ class TestIssuingDistributionPointExtension(object):
only_some_reasons=None,
indirect_crl=True,
only_contains_attribute_certs=False,
- )
+ ),
),
(
"crl_idp_fullname_only.pem",
x509.IssuingDistributionPoint(
full_name=[
x509.UniformResourceIdentifier(
- u"http://myhost.com/myca.crl")
+ u"http://myhost.com/myca.crl"
+ )
],
relative_name=None,
only_contains_user_certs=False,
@@ -4473,14 +4892,15 @@ class TestIssuingDistributionPointExtension(object):
only_some_reasons=None,
indirect_crl=False,
only_contains_attribute_certs=False,
- )
+ ),
),
(
"crl_idp_fullname_only_aa.pem",
x509.IssuingDistributionPoint(
full_name=[
x509.UniformResourceIdentifier(
- u"http://myhost.com/myca.crl")
+ u"http://myhost.com/myca.crl"
+ )
],
relative_name=None,
only_contains_user_certs=False,
@@ -4488,14 +4908,15 @@ class TestIssuingDistributionPointExtension(object):
only_some_reasons=None,
indirect_crl=False,
only_contains_attribute_certs=True,
- )
+ ),
),
(
"crl_idp_fullname_only_user.pem",
x509.IssuingDistributionPoint(
full_name=[
x509.UniformResourceIdentifier(
- u"http://myhost.com/myca.crl")
+ u"http://myhost.com/myca.crl"
+ )
],
relative_name=None,
only_contains_user_certs=True,
@@ -4503,23 +4924,26 @@ class TestIssuingDistributionPointExtension(object):
only_some_reasons=None,
indirect_crl=False,
only_contains_attribute_certs=False,
- )
+ ),
),
(
"crl_idp_only_ca.pem",
x509.IssuingDistributionPoint(
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
- )
- ]),
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME,
+ value=u"PyCA",
+ )
+ ]
+ ),
only_contains_user_certs=False,
only_contains_ca_certs=True,
only_some_reasons=None,
indirect_crl=False,
only_contains_attribute_certs=False,
- )
+ ),
),
(
"crl_idp_reasons_only.pem",
@@ -4528,62 +4952,71 @@ class TestIssuingDistributionPointExtension(object):
relative_name=None,
only_contains_user_certs=False,
only_contains_ca_certs=False,
- only_some_reasons=frozenset([
- x509.ReasonFlags.key_compromise
- ]),
+ only_some_reasons=frozenset(
+ [x509.ReasonFlags.key_compromise]
+ ),
indirect_crl=False,
only_contains_attribute_certs=False,
- )
+ ),
),
(
"crl_idp_relative_user_all_reasons.pem",
x509.IssuingDistributionPoint(
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
- )
- ]),
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME,
+ value=u"PyCA",
+ )
+ ]
+ ),
only_contains_user_certs=True,
only_contains_ca_certs=False,
- only_some_reasons=frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- x509.ReasonFlags.affiliation_changed,
- x509.ReasonFlags.superseded,
- x509.ReasonFlags.cessation_of_operation,
- x509.ReasonFlags.certificate_hold,
- x509.ReasonFlags.privilege_withdrawn,
- x509.ReasonFlags.aa_compromise,
- ]),
+ only_some_reasons=frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ x509.ReasonFlags.affiliation_changed,
+ x509.ReasonFlags.superseded,
+ x509.ReasonFlags.cessation_of_operation,
+ x509.ReasonFlags.certificate_hold,
+ x509.ReasonFlags.privilege_withdrawn,
+ x509.ReasonFlags.aa_compromise,
+ ]
+ ),
indirect_crl=False,
only_contains_attribute_certs=False,
- )
+ ),
),
(
"crl_idp_relativename_only.pem",
x509.IssuingDistributionPoint(
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
- )
- ]),
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME,
+ value=u"PyCA",
+ )
+ ]
+ ),
only_contains_user_certs=False,
only_contains_ca_certs=False,
only_some_reasons=None,
indirect_crl=False,
only_contains_attribute_certs=False,
- )
+ ),
),
- ]
+ ],
)
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_vectors(self, filename, expected, backend):
crl = _load_cert(
os.path.join("x509", "custom", filename),
- x509.load_pem_x509_crl, backend
+ x509.load_pem_x509_crl,
+ backend,
)
idp = crl.extensions.get_extension_for_class(
x509.IssuingDistributionPoint
@@ -4592,51 +5025,96 @@ class TestIssuingDistributionPointExtension(object):
@pytest.mark.parametrize(
(
- "error", "only_contains_user_certs", "only_contains_ca_certs",
- "indirect_crl", "only_contains_attribute_certs",
- "only_some_reasons", "full_name", "relative_name"
+ "error",
+ "only_contains_user_certs",
+ "only_contains_ca_certs",
+ "indirect_crl",
+ "only_contains_attribute_certs",
+ "only_some_reasons",
+ "full_name",
+ "relative_name",
),
[
(
- TypeError, False, False, False, False, 'notafrozenset', None,
- None
+ TypeError,
+ False,
+ False,
+ False,
+ False,
+ "notafrozenset",
+ None,
+ None,
),
(
- TypeError, False, False, False, False, frozenset(['bad']),
- None, None
+ TypeError,
+ False,
+ False,
+ False,
+ False,
+ frozenset(["bad"]),
+ None,
+ None,
),
(
- ValueError, False, False, False, False,
- frozenset([x509.ReasonFlags.unspecified]), None, None
+ ValueError,
+ False,
+ False,
+ False,
+ False,
+ frozenset([x509.ReasonFlags.unspecified]),
+ None,
+ None,
),
(
- ValueError, False, False, False, False,
- frozenset([x509.ReasonFlags.remove_from_crl]), None, None
+ ValueError,
+ False,
+ False,
+ False,
+ False,
+ frozenset([x509.ReasonFlags.remove_from_crl]),
+ None,
+ None,
),
- (TypeError, 'notabool', False, False, False, None, None, None),
- (TypeError, False, 'notabool', False, False, None, None, None),
- (TypeError, False, False, 'notabool', False, None, None, None),
- (TypeError, False, False, False, 'notabool', None, None, None),
+ (TypeError, "notabool", False, False, False, None, None, None),
+ (TypeError, False, "notabool", False, False, None, None, None),
+ (TypeError, False, False, "notabool", False, None, None, None),
+ (TypeError, False, False, False, "notabool", None, None, None),
(ValueError, True, True, False, False, None, None, None),
(ValueError, False, False, True, True, None, None, None),
(ValueError, False, False, False, False, None, None, None),
- ]
+ ],
)
- def test_invalid_init(self, error, only_contains_user_certs,
- only_contains_ca_certs, indirect_crl,
- only_contains_attribute_certs, only_some_reasons,
- full_name, relative_name):
+ def test_invalid_init(
+ self,
+ error,
+ only_contains_user_certs,
+ only_contains_ca_certs,
+ indirect_crl,
+ only_contains_attribute_certs,
+ only_some_reasons,
+ full_name,
+ relative_name,
+ ):
with pytest.raises(error):
x509.IssuingDistributionPoint(
- full_name, relative_name, only_contains_user_certs,
- only_contains_ca_certs, only_some_reasons, indirect_crl,
- only_contains_attribute_certs
+ full_name,
+ relative_name,
+ only_contains_user_certs,
+ only_contains_ca_certs,
+ only_some_reasons,
+ indirect_crl,
+ only_contains_attribute_certs,
)
def test_repr(self):
idp = x509.IssuingDistributionPoint(
- None, None, False, False,
- frozenset([x509.ReasonFlags.key_compromise]), False, False
+ None,
+ None,
+ False,
+ False,
+ frozenset([x509.ReasonFlags.key_compromise]),
+ False,
+ False,
)
if not six.PY2:
assert repr(idp) == (
@@ -4663,10 +5141,13 @@ class TestIssuingDistributionPointExtension(object):
only_contains_attribute_certs=False,
only_some_reasons=None,
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
- ])
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+ )
+ ]
+ ),
)
idp2 = x509.IssuingDistributionPoint(
only_contains_user_certs=False,
@@ -4675,10 +5156,13 @@ class TestIssuingDistributionPointExtension(object):
only_contains_attribute_certs=False,
only_some_reasons=None,
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
- ])
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+ )
+ ]
+ ),
)
assert idp1 == idp2
@@ -4690,10 +5174,13 @@ class TestIssuingDistributionPointExtension(object):
only_contains_attribute_certs=False,
only_some_reasons=None,
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
- ])
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+ )
+ ]
+ ),
)
idp2 = x509.IssuingDistributionPoint(
only_contains_user_certs=True,
@@ -4702,10 +5189,13 @@ class TestIssuingDistributionPointExtension(object):
only_contains_attribute_certs=False,
only_some_reasons=None,
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
- ])
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+ )
+ ]
+ ),
)
assert idp1 != idp2
assert idp1 != object()
@@ -4719,11 +5209,18 @@ class TestIssuingDistributionPointExtension(object):
)
idp3 = x509.IssuingDistributionPoint(
None,
- x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
- ]),
- True, False, None, False, False
+ x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+ )
+ ]
+ ),
+ True,
+ False,
+ None,
+ False,
+ False,
)
assert hash(idp1) == hash(idp2)
assert hash(idp1) != hash(idp3)
@@ -4787,11 +5284,13 @@ class TestIssuingDistributionPointExtension(object):
),
x509.IssuingDistributionPoint(
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
- )
- ]),
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+ )
+ ]
+ ),
only_contains_user_certs=False,
only_contains_ca_certs=True,
only_some_reasons=None,
@@ -4809,53 +5308,65 @@ class TestIssuingDistributionPointExtension(object):
),
x509.IssuingDistributionPoint(
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"),
- x509.NameAttribute(
- oid=x509.NameOID.COMMON_NAME, value=u"cryptography")
- ]),
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+ ),
+ x509.NameAttribute(
+ oid=x509.NameOID.COMMON_NAME, value=u"cryptography"
+ ),
+ ]
+ ),
only_contains_user_certs=True,
only_contains_ca_certs=False,
- only_some_reasons=frozenset([
- x509.ReasonFlags.key_compromise,
- x509.ReasonFlags.ca_compromise,
- x509.ReasonFlags.affiliation_changed,
- x509.ReasonFlags.privilege_withdrawn,
- x509.ReasonFlags.aa_compromise,
- ]),
+ only_some_reasons=frozenset(
+ [
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ x509.ReasonFlags.affiliation_changed,
+ x509.ReasonFlags.privilege_withdrawn,
+ x509.ReasonFlags.aa_compromise,
+ ]
+ ),
indirect_crl=False,
only_contains_attribute_certs=False,
),
x509.IssuingDistributionPoint(
full_name=None,
- relative_name=x509.RelativeDistinguishedName([
- x509.NameAttribute(
- oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
- )
- ]),
+ relative_name=x509.RelativeDistinguishedName(
+ [
+ x509.NameAttribute(
+ oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
+ )
+ ]
+ ),
only_contains_user_certs=False,
only_contains_ca_certs=False,
only_some_reasons=None,
indirect_crl=False,
only_contains_attribute_certs=False,
),
- ]
+ ],
)
def test_generate(self, idp, backend):
key = RSA_KEY_2048.private_key(backend)
last_update = datetime.datetime(2002, 1, 1, 12, 1)
next_update = datetime.datetime(2030, 1, 1, 12, 1)
- builder = x509.CertificateRevocationListBuilder().issuer_name(
- x509.Name([
- x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
- ])
- ).last_update(
- last_update
- ).next_update(
- next_update
- ).add_extension(
- idp, True
+ builder = (
+ x509.CertificateRevocationListBuilder()
+ .issuer_name(
+ x509.Name(
+ [
+ x509.NameAttribute(
+ NameOID.COMMON_NAME, u"cryptography.io CA"
+ )
+ ]
+ )
+ )
+ .last_update(last_update)
+ .next_update(next_update)
+ .add_extension(idp, True)
)
crl = builder.sign(key, hashes.SHA256(), backend)
@@ -4873,7 +5384,7 @@ class TestPrecertPoisonExtension(object):
cert = _load_cert(
os.path.join("x509", "cryptography.io.precert.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
poison = cert.extensions.get_extension_for_oid(
ExtensionOID.PRECERT_POISON
@@ -4886,90 +5397,142 @@ class TestPrecertPoisonExtension(object):
def test_generate(self, backend):
private_key = RSA_KEY_2048.private_key(backend)
- cert = _make_certbuilder(private_key).add_extension(
- x509.PrecertPoison(), critical=True
- ).sign(private_key, hashes.SHA256(), backend)
+ cert = (
+ _make_certbuilder(private_key)
+ .add_extension(x509.PrecertPoison(), critical=True)
+ .sign(private_key, hashes.SHA256(), backend)
+ )
poison = cert.extensions.get_extension_for_oid(
ExtensionOID.PRECERT_POISON
).value
assert isinstance(poison, x509.PrecertPoison)
+ def test_eq(self):
+ pcp1 = x509.PrecertPoison()
+ pcp2 = x509.PrecertPoison()
+
+ assert pcp1 == pcp2
+
+ def test_hash(self):
+ pcp1 = x509.PrecertPoison()
+ pcp2 = x509.PrecertPoison()
+
+ assert hash(pcp1) == hash(pcp2)
+
+ def test_ne(self):
+ pcp1 = x509.PrecertPoison()
+ pcp2 = x509.PrecertPoison()
+
+ assert pcp1 == pcp2
+ assert (pcp1 != pcp2) is False
+ assert pcp1 != object()
+
+ def test_repr(self):
+ pcp = x509.PrecertPoison()
+
+ assert repr(pcp) == "<PrecertPoison()>"
+
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
class TestSignedCertificateTimestamps(object):
@pytest.mark.supported(
- only_if=lambda backend: (
- backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
- skip_message="Requires OpenSSL 1.1.0f+",
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
)
def test_eq(self, backend):
- sct = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value[0]
- sct2 = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value[0]
+ sct = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value[0]
+ )
+ sct2 = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value[0]
+ )
assert sct == sct2
@pytest.mark.supported(
- only_if=lambda backend: (
- backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
- skip_message="Requires OpenSSL 1.1.0f+",
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
)
def test_ne(self, backend):
- sct = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value[0]
- sct2 = _load_cert(
- os.path.join("x509", "cryptography-scts.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value[0]
+ sct = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value[0]
+ )
+ sct2 = (
+ _load_cert(
+ os.path.join("x509", "cryptography-scts.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value[0]
+ )
assert sct != sct2
assert sct != object()
@pytest.mark.supported(
- only_if=lambda backend: (
- backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
- skip_message="Requires OpenSSL 1.1.0f+",
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
)
def test_hash(self, backend):
- sct = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value[0]
- sct2 = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value[0]
- sct3 = _load_cert(
- os.path.join("x509", "cryptography-scts.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value[0]
+ sct = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value[0]
+ )
+ sct2 = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value[0]
+ )
+ sct3 = (
+ _load_cert(
+ os.path.join("x509", "cryptography-scts.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value[0]
+ )
assert hash(sct) == hash(sct2)
assert hash(sct) != hash(sct3)
@@ -4987,90 +5550,114 @@ class TestPrecertificateSignedCertificateTimestampsExtension(object):
)
@pytest.mark.supported(
- only_if=lambda backend: (
- backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
- skip_message="Requires OpenSSL 1.1.0f+",
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
)
def test_eq(self, backend):
- psct1 = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value
- psct2 = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value
+ psct1 = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value
+ )
+ psct2 = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value
+ )
assert psct1 == psct2
@pytest.mark.supported(
- only_if=lambda backend: (
- backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
- skip_message="Requires OpenSSL 1.1.0f+",
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
)
def test_ne(self, backend):
- psct1 = _load_cert(
- os.path.join("x509", "cryptography-scts.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value
- psct2 = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value
+ psct1 = (
+ _load_cert(
+ os.path.join("x509", "cryptography-scts.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value
+ )
+ psct2 = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value
+ )
assert psct1 != psct2
assert psct1 != object()
@pytest.mark.supported(
- only_if=lambda backend: (
- backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
- skip_message="Requires OpenSSL 1.1.0f+",
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
)
def test_hash(self, backend):
- psct1 = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value
- psct2 = _load_cert(
- os.path.join("x509", "badssl-sct.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value
- psct3 = _load_cert(
- os.path.join("x509", "cryptography-scts.pem"),
- x509.load_pem_x509_certificate,
- backend
- ).extensions.get_extension_for_class(
- x509.PrecertificateSignedCertificateTimestamps
- ).value
+ psct1 = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value
+ )
+ psct2 = (
+ _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value
+ )
+ psct3 = (
+ _load_cert(
+ os.path.join("x509", "cryptography-scts.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ .extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ )
+ .value
+ )
assert hash(psct1) == hash(psct2)
assert hash(psct1) != hash(psct3)
@pytest.mark.supported(
- only_if=lambda backend: (
- backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
- skip_message="Requires OpenSSL 1.1.0f+",
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
)
def test_simple(self, backend):
cert = _load_cert(
os.path.join("x509", "badssl-sct.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
scts = cert.extensions.get_extension_for_class(
x509.PrecertificateSignedCertificateTimestamps
@@ -5087,20 +5674,46 @@ class TestPrecertificateSignedCertificateTimestampsExtension(object):
2016, 11, 17, 1, 56, 25, 396000
)
assert (
- sct.entry_type ==
- x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE
+ sct.entry_type
+ == x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE
)
@pytest.mark.supported(
- only_if=lambda backend: (
- not backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER),
- skip_message="Requires OpenSSL < 1.1.0",
+ only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT),
+ skip_message="Requires CT support",
+ )
+ def test_generate(self, backend):
+ cert = _load_cert(
+ os.path.join("x509", "badssl-sct.pem"),
+ x509.load_pem_x509_certificate,
+ backend,
+ )
+ scts = cert.extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ ).value
+ assert len(scts) == 1
+ [sct] = scts
+
+ private_key = RSA_KEY_2048.private_key(backend)
+ builder = _make_certbuilder(private_key).add_extension(
+ x509.PrecertificateSignedCertificateTimestamps([sct]),
+ critical=False,
+ )
+ cert = builder.sign(private_key, hashes.SHA256(), backend)
+ ext = cert.extensions.get_extension_for_class(
+ x509.PrecertificateSignedCertificateTimestamps
+ ).value
+ assert list(ext) == [sct]
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend._lib.CRYPTOGRAPHY_IS_LIBRESSL,
+ skip_message="Requires LibreSSL",
)
def test_skips_scts_if_unsupported(self, backend):
cert = _load_cert(
os.path.join("x509", "badssl-sct.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
assert len(cert.extensions) == 10
with pytest.raises(x509.ExtensionNotFound):
@@ -5119,11 +5732,9 @@ class TestPrecertificateSignedCertificateTimestampsExtension(object):
class TestInvalidExtension(object):
def test_invalid_certificate_policies_data(self, backend):
cert = _load_cert(
- os.path.join(
- "x509", "custom", "cp_invalid.pem"
- ),
+ os.path.join("x509", "custom", "cp_invalid.pem"),
x509.load_pem_x509_certificate,
- backend
+ backend,
)
with pytest.raises(ValueError):
cert.extensions
@@ -5158,3 +5769,10 @@ class TestOCSPNonce(object):
nonce3 = x509.OCSPNonce(b"1" * 5)
assert hash(nonce1) == hash(nonce2)
assert hash(nonce1) != hash(nonce3)
+
+
+def test_all_extension_oid_members_have_names_defined():
+ for oid in dir(ExtensionOID):
+ if oid.startswith("__"):
+ continue
+ assert getattr(ExtensionOID, oid) in _OID_NAMES
diff --git a/tests/x509/test_x509_revokedcertbuilder.py b/tests/x509/test_x509_revokedcertbuilder.py
index 75c6b2697..0db6d2a6f 100644
--- a/tests/x509/test_x509_revokedcertbuilder.py
+++ b/tests/x509/test_x509_revokedcertbuilder.py
@@ -30,10 +30,10 @@ class TestRevokedCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_minimal_serial_number(self, backend):
revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
- builder = x509.RevokedCertificateBuilder().serial_number(
- 1
- ).revocation_date(
- revocation_date
+ builder = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(1)
+ .revocation_date(revocation_date)
)
revoked_certificate = builder.build(backend)
@@ -42,10 +42,10 @@ class TestRevokedCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_biggest_serial_number(self, backend):
revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
- builder = x509.RevokedCertificateBuilder().serial_number(
- (1 << 159) - 1
- ).revocation_date(
- revocation_date
+ builder = (
+ x509.RevokedCertificateBuilder()
+ .serial_number((1 << 159) - 1)
+ .revocation_date(revocation_date)
)
revoked_certificate = builder.build(backend)
@@ -67,10 +67,10 @@ class TestRevokedCertificateBuilder(object):
time = tz.localize(time)
utc_time = datetime.datetime(2012, 1, 17, 6, 43)
serial_number = 333
- builder = x509.RevokedCertificateBuilder().serial_number(
- serial_number
- ).revocation_date(
- time
+ builder = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(serial_number)
+ .revocation_date(time)
)
revoked_certificate = builder.build(backend)
@@ -129,10 +129,10 @@ class TestRevokedCertificateBuilder(object):
def test_create_revoked(self, backend):
serial_number = 333
revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
- builder = x509.RevokedCertificateBuilder().serial_number(
- serial_number
- ).revocation_date(
- revocation_date
+ builder = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(serial_number)
+ .revocation_date(revocation_date)
)
revoked_certificate = builder.build(backend)
@@ -145,21 +145,18 @@ class TestRevokedCertificateBuilder(object):
[
x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0)),
x509.CRLReason(x509.ReasonFlags.ca_compromise),
- x509.CertificateIssuer([
- x509.DNSName(u"cryptography.io"),
- ])
- ]
+ x509.CertificateIssuer([x509.DNSName(u"cryptography.io")]),
+ ],
)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_add_extensions(self, backend, extension):
serial_number = 333
revocation_date = datetime.datetime(2002, 1, 1, 12, 1)
- builder = x509.RevokedCertificateBuilder().serial_number(
- serial_number
- ).revocation_date(
- revocation_date
- ).add_extension(
- extension, False
+ builder = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(serial_number)
+ .revocation_date(revocation_date)
+ .add_extension(extension, False)
)
revoked_certificate = builder.build(backend)
@@ -179,20 +176,17 @@ class TestRevokedCertificateBuilder(object):
invalidity_date = x509.InvalidityDate(
datetime.datetime(2015, 1, 1, 0, 0)
)
- certificate_issuer = x509.CertificateIssuer([
- x509.DNSName(u"cryptography.io"),
- ])
+ certificate_issuer = x509.CertificateIssuer(
+ [x509.DNSName(u"cryptography.io")]
+ )
crl_reason = x509.CRLReason(x509.ReasonFlags.aa_compromise)
- builder = x509.RevokedCertificateBuilder().serial_number(
- serial_number
- ).revocation_date(
- revocation_date
- ).add_extension(
- invalidity_date, True
- ).add_extension(
- crl_reason, True
- ).add_extension(
- certificate_issuer, True
+ builder = (
+ x509.RevokedCertificateBuilder()
+ .serial_number(serial_number)
+ .revocation_date(revocation_date)
+ .add_extension(invalidity_date, True)
+ .add_extension(crl_reason, True)
+ .add_extension(certificate_issuer, True)
)
revoked_certificate = builder.build(backend)
diff --git a/tox.ini b/tox.ini
index d4c3022bc..e6e04575b 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,20 +1,22 @@
[tox]
minversion = 2.4
-envlist = py27,pypy,py34,py35,py36,py37,docs,pep8,py3pep8
+envlist = py27,pypy,py36,py37,py38,py39,docs,pep8,packaging
+isolated_build = True
[testenv]
extras =
- test
- idna: idna
+ test
+ ssh: ssh
deps =
- # This must be kept in sync with Jenkinsfile and .travis/install.sh
+ # This must be kept in sync with .github/workflows/ci.yml
coverage
./vectors
-passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME
+ randomorder: pytest-randomly
+passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING OPENSSL_FORCE_FIPS_MODE
commands =
pip list
# We use parallel mode and then combine here so that coverage.py will take
- # the paths like .tox/py34/lib/python3.4/site-packages/cryptography/__init__.py
+ # the paths like .tox/py38/lib/python3.8/site-packages/cryptography/__init__.py
# and collapse them into src/cryptography/__init__.py.
coverage run --parallel-mode -m pytest --capture=no --strict {posargs}
coverage combine
@@ -42,10 +44,10 @@ extras =
docstest
basepython = python3
commands =
- sphinx-build -j4 -T -W -b html -d {envtmpdir}/doctrees docs docs/_build/html
- sphinx-build -j4 -T -W -b latex -d {envtmpdir}/doctrees docs docs/_build/latex
- sphinx-build -j4 -T -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html
- sphinx-build -j4 -T -W -b spelling docs docs/_build/html
+ sphinx-build -T -W -b html -d {envtmpdir}/doctrees docs docs/_build/html
+ sphinx-build -T -W -b latex -d {envtmpdir}/doctrees docs docs/_build/latex
+ sphinx-build -T -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html
+ sphinx-build -T -W -b spelling docs docs/_build/html
doc8 --allow-long-titles README.rst CHANGELOG.rst docs/ --ignore-path docs/_build/
python setup.py sdist
twine check dist/*
@@ -53,26 +55,26 @@ commands =
[testenv:docs-linkcheck]
extras =
docs
-basepython = python2.7
+basepython = python3
commands =
sphinx-build -W -b linkcheck docs docs/_build/html
[testenv:pep8]
basepython = python3
extras =
- pep8test
+ pep8test
commands =
flake8 .
+ black --check .
-[testenv:randomorder]
+[testenv:packaging]
deps =
- {[testenv]deps}
- pytest-random
+ check-manifest
commands =
- pytest --capture=no --strict --random {posargs}
+ check-manifest
[flake8]
-ignore = W504
+ignore = E203,E211,W503,W504
exclude = .tox,*.egg,.git,_build,.hypothesis
select = E,W,F,N,I
application-import-names = cryptography,cryptography_vectors,tests
@@ -84,5 +86,6 @@ extensions = rst
addopts = -r s
markers =
requires_backend_interface: this test requires a specific backend interface
+ skip_fips: this test is not executed in FIPS mode
supported: parametrized test requiring only_if and skip_message
wycheproof_tests: this test runs a wycheproof fixture
diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py
index 6fcb314e2..dc069d51b 100644
--- a/vectors/cryptography_vectors/__about__.py
+++ b/vectors/cryptography_vectors/__about__.py
@@ -5,8 +5,14 @@
from __future__ import absolute_import, division, print_function
__all__ = [
- "__title__", "__summary__", "__uri__", "__version__", "__author__",
- "__email__", "__license__", "__copyright__",
+ "__title__",
+ "__summary__",
+ "__uri__",
+ "__version__",
+ "__author__",
+ "__email__",
+ "__license__",
+ "__copyright__",
]
__title__ = "cryptography_vectors"
@@ -14,10 +20,10 @@ __summary__ = "Test vectors for the cryptography package."
__uri__ = "https://github.com/pyca/cryptography"
-__version__ = "2.5"
+__version__ = "3.3.2"
__author__ = "The cryptography developers"
__email__ = "cryptography-dev@python.org"
__license__ = "BSD or Apache License, Version 2.0"
-__copyright__ = "Copyright 2013-2017 %s" % __author__
+__copyright__ = "Copyright 2013-2021 %s" % __author__
diff --git a/vectors/cryptography_vectors/__init__.py b/vectors/cryptography_vectors/__init__.py
index abcfe14c2..f39ffe03a 100644
--- a/vectors/cryptography_vectors/__init__.py
+++ b/vectors/cryptography_vectors/__init__.py
@@ -7,14 +7,26 @@ from __future__ import absolute_import, division, print_function
import os
from cryptography_vectors.__about__ import (
- __author__, __copyright__, __email__, __license__, __summary__, __title__,
- __uri__, __version__
+ __author__,
+ __copyright__,
+ __email__,
+ __license__,
+ __summary__,
+ __title__,
+ __uri__,
+ __version__,
)
__all__ = [
- "__title__", "__summary__", "__uri__", "__version__", "__author__",
- "__email__", "__license__", "__copyright__",
+ "__title__",
+ "__summary__",
+ "__uri__",
+ "__version__",
+ "__author__",
+ "__email__",
+ "__license__",
+ "__copyright__",
]
diff --git a/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.der b/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.der
new file mode 100644
index 000000000..7358bc1de
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_invalid_bit_string.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_no_params.der b/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_no_params.der
new file mode 100644
index 000000000..0270ac158
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DER_Serialization/dsa_public_key_no_params.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem b/vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem
new file mode 100644
index 000000000..1c01dd3ea
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MFwCAQAwMwYJKoZIhvcNAQMBMCYCIQCBPg6BS+5nbb09nSjtc9NnNdIf9kVyNvaN
+PWFFVgwPqwIBAgQiAiBmJ3qBbu72ZnUxnCrr8ujWFU7jWTcOjhsZSqobmiD6vA==
+-----END PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.der b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.der
new file mode 100644
index 000000000..f268ed1bf
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.pem b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.pem
new file mode 100644
index 000000000..d4bcdb2a4
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8-enc.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAhDgfwSFbYckgICCAAw
+DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEFR6pN0F5UEPFF/Z8RB0maoEQG0i
+za5Fgv9/c8H9med7ttjbbh8T73t+Rq2dcFT2kcUM2HJWGrWMvDpTEPEy0hduYFDh
+YMcDjtOCKyUTwPovQI0=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.der b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.der
new file mode 100644
index 000000000..71783b74d
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.pem b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.pem
new file mode 100644
index 000000000..7cf2b728c
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pkcs8.pem
@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEIJ1hsZ3v/VpguoRK9JLsLMREScVpezJpGXA7rAMcrn9g
+-----END PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.der b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.der
new file mode 100644
index 000000000..5b33e7546
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.pem b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.pem
new file mode 100644
index 000000000..9749b691d
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed25519/ed25519-pub.pem
@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=
+-----END PUBLIC KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.der b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.der
new file mode 100644
index 000000000..0ac1c2662
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.pem b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.pem
new file mode 100644
index 000000000..c1911db52
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8-enc.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGrMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAi70Zc5kmb1BQICCAAw
+DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEKLz9IxrHtLE/xwZXVFlzxcEUIdP
+7Z+POIUbdwM2TT9GsYoh/RoHzbSszd873muKzCE6YclamsDhLL8HCS82tGN9ZzgK
+IuNWwcPeskw1i21MLoPJiS76RfncGROVDiz3CKCp
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.der b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.der
new file mode 100644
index 000000000..5718a5473
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.pem b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.pem
new file mode 100644
index 000000000..98af16420
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pkcs8.pem
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MEcCAQAwBQYDK2VxBDsEOWyCpWLLgI0Q1jK+ichRPr9skp803fqMn2PJlg7240ij
+UoyKP8wvBE45o/xblEkvjwMudUmiAJj5Ww==
+-----END PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.der b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.der
new file mode 100644
index 000000000..bd2a95530
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.der
Binary files differ
diff --git a/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.pem b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.pem
new file mode 100644
index 000000000..640da6f2b
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/Ed448/ed448-pub.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MEMwBQYDK2VxAzoAX9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2
+m0bHBhvWeD3x5Q9s0foavq/oJWGA
+-----END PUBLIC KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key
new file mode 100644
index 000000000..edb69615f
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key
@@ -0,0 +1,21 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH
+NzAAAAgQDRqiBQV8QY6a/5fUvFCs5koeJgXj1v2D6dlSqEBEEu8aRA/sJQZmSx6Xzoi9gl
+nvyrS0/Sjf0Y4J5iU1D0gYsNzBhxZFFyrg6LExwSfqMcWWBw8pdcMcOjVfrcWohvqF/Na2
+EnzTZgSOX3WbXA8ikw1Irak5MvD7luNDLX2ZKi7wAAABUA9x8+++PeaLuNjNUvbaDXhvmw
+jbcAAACBAKlkeJEdFVDpZDmMG2Ob8KXy8hrqfEwZHR1B0HPWmZoOpw+TpY/oYEwuA9mXSG
+0EeDVcQlBIaAtu4ZfmZQnRQ5cZ+cBX8VnxAAR6JUQw5R00U6cbiDSYXDn93sLW+D27f1jn
+NShsyz43F66LrsXWTLmoFtMKXw+YBL5cL7Mfk6OcAAAAgHqgOmrZJRmNiRJAY/0ylOB9pc
+S0OfYSj3MXIgbkS0qRvR+Llv1QpFCqykzTEFONosZb75Jb3FuIqw1WdZBOM8ZF5dIBdHAs
+Q01NoTZiHJRQlFwBqMZ4DCs3txDuM1GZmDaYWIRdzVnrq8USqBSo2t1BvXbZXFLcmHsIyh
+xh9CusAAAB6BxKLVkcSi1ZAAAAB3NzaC1kc3MAAACBANGqIFBXxBjpr/l9S8UKzmSh4mBe
+PW/YPp2VKoQEQS7xpED+wlBmZLHpfOiL2CWe/KtLT9KN/RjgnmJTUPSBiw3MGHFkUXKuDo
+sTHBJ+oxxZYHDyl1wxw6NV+txaiG+oX81rYSfNNmBI5fdZtcDyKTDUitqTky8PuW40MtfZ
+kqLvAAAAFQD3Hz77495ou42M1S9toNeG+bCNtwAAAIEAqWR4kR0VUOlkOYwbY5vwpfLyGu
+p8TBkdHUHQc9aZmg6nD5Olj+hgTC4D2ZdIbQR4NVxCUEhoC27hl+ZlCdFDlxn5wFfxWfEA
+BHolRDDlHTRTpxuINJhcOf3ewtb4Pbt/WOc1KGzLPjcXrouuxdZMuagW0wpfD5gEvlwvsx
++To5wAAACAeqA6atklGY2JEkBj/TKU4H2lxLQ59hKPcxciBuRLSpG9H4uW/VCkUKrKTNMQ
+U42ixlvvklvcW4irDVZ1kE4zxkXl0gF0cCxDTU2hNmIclFCUXAGoxngMKze3EO4zUZmYNp
+hYhF3NWeurxRKoFKja3UG9dtlcUtyYewjKHGH0K6wAAAAVAMS2BFSZWFdWHlyYZscEHEEv
+TkRNAAAADWRzYS1ub3Bzdy5rZXkBAgME
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key-cert.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key-cert.pub
new file mode 100644
index 000000000..753989db5
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key-cert.pub
@@ -0,0 +1 @@
+ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgT/srHasDLk3rB8bDZK7rP6miircgVvnVrTghYfkmZsEAAACBANGqIFBXxBjpr/l9S8UKzmSh4mBePW/YPp2VKoQEQS7xpED+wlBmZLHpfOiL2CWe/KtLT9KN/RjgnmJTUPSBiw3MGHFkUXKuDosTHBJ+oxxZYHDyl1wxw6NV+txaiG+oX81rYSfNNmBI5fdZtcDyKTDUitqTky8PuW40MtfZkqLvAAAAFQD3Hz77495ou42M1S9toNeG+bCNtwAAAIEAqWR4kR0VUOlkOYwbY5vwpfLyGup8TBkdHUHQc9aZmg6nD5Olj+hgTC4D2ZdIbQR4NVxCUEhoC27hl+ZlCdFDlxn5wFfxWfEABHolRDDlHTRTpxuINJhcOf3ewtb4Pbt/WOc1KGzLPjcXrouuxdZMuagW0wpfD5gEvlwvsx+To5wAAACAeqA6atklGY2JEkBj/TKU4H2lxLQ59hKPcxciBuRLSpG9H4uW/VCkUKrKTNMQU42ixlvvklvcW4irDVZ1kE4zxkXl0gF0cCxDTU2hNmIclFCUXAGoxngMKze3EO4zUZmYNphYhF3NWeurxRKoFKja3UG9dtlcUtyYewjKHGH0K6wAAAAAAAAAAQAAAAEAAAAEbmFtZQAAAAAAAAAASz3OqAAAAAEFdF0oAAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAbIAAAAHc3NoLWRzcwAAAIEA0aogUFfEGOmv+X1LxQrOZKHiYF49b9g+nZUqhARBLvGkQP7CUGZksel86IvYJZ78q0tP0o39GOCeYlNQ9IGLDcwYcWRRcq4OixMcEn6jHFlgcPKXXDHDo1X63FqIb6hfzWthJ802YEjl91m1wPIpMNSK2pOTLw+5bjQy19mSou8AAAAVAPcfPvvj3mi7jYzVL22g14b5sI23AAAAgQCpZHiRHRVQ6WQ5jBtjm/Cl8vIa6nxMGR0dQdBz1pmaDqcPk6WP6GBMLgPZl0htBHg1XEJQSGgLbuGX5mUJ0UOXGfnAV/FZ8QAEeiVEMOUdNFOnG4g0mFw5/d7C1vg9u39Y5zUobMs+Nxeui67F1ky5qBbTCl8PmAS+XC+zH5OjnAAAAIB6oDpq2SUZjYkSQGP9MpTgfaXEtDn2Eo9zFyIG5EtKkb0fi5b9UKRQqspM0xBTjaLGW++SW9xbiKsNVnWQTjPGReXSAXRwLENNTaE2YhyUUJRcAajGeAwrN7cQ7jNRmZg2mFiEXc1Z66vFEqgUqNrdQb122VxS3Jh7CMocYfQrrAAAADcAAAAHc3NoLWRzcwAAAChGJhskBvKjziUaQuE3Kd3A+3WqQduqROikisQyJqTEmD9CqCrV2tuQ dsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key.pub
new file mode 100644
index 000000000..b50e534c1
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-nopsw.key.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBANGqIFBXxBjpr/l9S8UKzmSh4mBePW/YPp2VKoQEQS7xpED+wlBmZLHpfOiL2CWe/KtLT9KN/RjgnmJTUPSBiw3MGHFkUXKuDosTHBJ+oxxZYHDyl1wxw6NV+txaiG+oX81rYSfNNmBI5fdZtcDyKTDUitqTky8PuW40MtfZkqLvAAAAFQD3Hz77495ou42M1S9toNeG+bCNtwAAAIEAqWR4kR0VUOlkOYwbY5vwpfLyGup8TBkdHUHQc9aZmg6nD5Olj+hgTC4D2ZdIbQR4NVxCUEhoC27hl+ZlCdFDlxn5wFfxWfEABHolRDDlHTRTpxuINJhcOf3ewtb4Pbt/WOc1KGzLPjcXrouuxdZMuagW0wpfD5gEvlwvsx+To5wAAACAeqA6atklGY2JEkBj/TKU4H2lxLQ59hKPcxciBuRLSpG9H4uW/VCkUKrKTNMQU42ixlvvklvcW4irDVZ1kE4zxkXl0gF0cCxDTU2hNmIclFCUXAGoxngMKze3EO4zUZmYNphYhF3NWeurxRKoFKja3UG9dtlcUtyYewjKHGH0K6w= dsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key
new file mode 100644
index 000000000..ee6d1e12b
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key
@@ -0,0 +1,22 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCOodUQio
+9QarE9NbbQUAuXAAAAEAAAAAEAAAGyAAAAB3NzaC1kc3MAAACBAMHOI6HG+xy8RLV6C1JS
+k3dldozdE3SJjK1n0UTdBFo/r1ZMnnH/IZOk5+TkRXplfkVAcmmH++Zm4yb4SzxiDMY8XB
+Tn0COzgPOfJJUV6TKLgAF8QsvlhDrbRgLk1ANPQRY3YIPrVGcF4oUZcyUkIcjl4kycGwMy
+E8wm0FckDKitAAAAFQC5WH7VkaACexO69dQapzGy05mb0QAAAIASiv/QUqr9zGVgiLj/Ge
+KlF7nZLJNCTRoIYGEdARQM23052a/aPMoxaHk3SKHZZmGU87Gp0vl4z6zwRYTp7pzwLqU3
+6gprOqcrFDrPhEq0xkU8+AKClLZ31BUyxN2u6kpBiwQI4Mme3z3PDLVSME+NMEn+sdZKQp
+L0Y0ctXBMtSQAAAIEAmahTrRyoQ32qVX3GKqHElryPfMjWIJsrGByxUNf3hn+IhTs4u858
+oHTiLsZWqrkxFqIGHSSrXclxVkvz9WxKO7D6tcECK7nCqmtEmgXGW+ayVUkeMRlv1VYHKx
+ePsLxOOip14A00vqY5MkZJ8zFFrHxFV0Ej8cKaxJ4SLmvAkM0AAAHwvffrsyCVDHxWqAg2
+KQEm+3ebumLdoLkGgDiSaO1jwJr3R1VnzQTtqveg4rm5agmeHKvUmDTd1lTyTWWk6zX6Bx
+Ww+63V+c3Byv0DlexJToQKo99ZayioWyJjF0/bRXJE34aIYzbDFCQTJdGQ2pEXAnyWBVOB
+j44w/P6VvdhTDvfIYk2ZLpnEPbBi38Hs3n2a2VSp/dNctfE4yfnf2aVntXPoJPRbOYNZs6
+AmcPacbkBXNV2LJeTP2dnXFM4mnReBRVF9Eqd4SsfEXDvC1beBBf9rZN3c/JKXohG97iPi
+PO4Bv34xMKVw64+RtyIN8gTE4Sp/ChqgESIGqCo034YQ5PYLlSX7JxzbfOkBZHAcg2MVsO
+npL1HizQp/l5JzxNrFhjg9ZtIwa5mmPapQ1T/IWQQ5lrtev5cWcfEYonhyvjn2F9Rd5Eem
+jajVfzUS37IGEN2vZaNyLmvMdemJMSkIQwHiHpsdcDfdR7m4hAIWnBYpj2+z5C4WuAFAqE
+UeHjiw9PIMNFK6JTo3QbEUddJw5jgdlx9nctM26JWwKBAOYINCOv5f/2gjR13DzkLL5Xca
+dSO1zHzdIZzrNpD/SFJFeHxlVuaCg6MefhYRMfxVZUAKYdw0qNhhTLecCfChQL6t2NdEOm
+q9f9gN2+a0fnO2lA==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key.pub
new file mode 100644
index 000000000..a9a8d5659
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/dsa-psw.key.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAMHOI6HG+xy8RLV6C1JSk3dldozdE3SJjK1n0UTdBFo/r1ZMnnH/IZOk5+TkRXplfkVAcmmH++Zm4yb4SzxiDMY8XBTn0COzgPOfJJUV6TKLgAF8QsvlhDrbRgLk1ANPQRY3YIPrVGcF4oUZcyUkIcjl4kycGwMyE8wm0FckDKitAAAAFQC5WH7VkaACexO69dQapzGy05mb0QAAAIASiv/QUqr9zGVgiLj/GeKlF7nZLJNCTRoIYGEdARQM23052a/aPMoxaHk3SKHZZmGU87Gp0vl4z6zwRYTp7pzwLqU36gprOqcrFDrPhEq0xkU8+AKClLZ31BUyxN2u6kpBiwQI4Mme3z3PDLVSME+NMEn+sdZKQpL0Y0ctXBMtSQAAAIEAmahTrRyoQ32qVX3GKqHElryPfMjWIJsrGByxUNf3hn+IhTs4u858oHTiLsZWqrkxFqIGHSSrXclxVkvz9WxKO7D6tcECK7nCqmtEmgXGW+ayVUkeMRlv1VYHKxePsLxOOip14A00vqY5MkZJ8zFFrHxFV0Ej8cKaxJ4SLmvAkM0= dsa-psw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key
new file mode 100644
index 000000000..4c0a8bf61
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key
@@ -0,0 +1,9 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
+1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQmVkbOBmCBxiacl7qr3xRljePXZyUZ
+GSSw5Bax3+pjR4SDCN77ay3wmcMT0n5wmFiumKH7LGdRWAOk5FSavF4vAAAAqGb/L/dm/y
+/3AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCZWRs4GYIHGJpyX
+uqvfFGWN49dnJRkZJLDkFrHf6mNHhIMI3vtrLfCZwxPSfnCYWK6YofssZ1FYA6TkVJq8Xi
+8AAAAgcFJtJbq8YCNzbVBuGxtFkMo6E7L6thbRA0FqV4+2MbAAAAAPZWNkc2Etbm9wc3cu
+a2V5AQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key-cert.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key-cert.pub
new file mode 100644
index 000000000..ce1626bad
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key-cert.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg7ohu2h3ZSjGNlNGn5wmDHarKBT8q+6Yl23V+s3MNjzEAAAAIbmlzdHAyNTYAAABBBCZWRs4GYIHGJpyXuqvfFGWN49dnJRkZJLDkFrHf6mNHhIMI3vtrLfCZwxPSfnCYWK6YofssZ1FYA6TkVJq8Xi8AAAAAAAAAAAAAAAIAAAAEbmFtZQAAABYAAAAHZG9tYWluMQAAAAdkb21haW4yAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAEEEJlZGzgZggcYmnJe6q98UZY3j12clGRkksOQWsd/qY0eEgwje+2st8JnDE9J+cJhYrpih+yxnUVgDpORUmrxeLwAAAGMAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAEgAAAAhAOSy1UooQNXaxG4cbZTQVnC7uSJlLuk4w9Z5XvbfzzmSAAAAH2QDu0n+WcXzDEsXeaH6IV0drX99PYLeiabxYeUha/o= ecdsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key.pub
new file mode 100644
index 000000000..17f28a635
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-nopsw.key.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCZWRs4GYIHGJpyXuqvfFGWN49dnJRkZJLDkFrHf6mNHhIMI3vtrLfCZwxPSfnCYWK6YofssZ1FYA6TkVJq8Xi8= ecdsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key
new file mode 100644
index 000000000..35eb8814e
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key
@@ -0,0 +1,11 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBNPqCdPL
+3HMhcAs6vsUbVEAAAAEAAAAAEAAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlz
+dHAzODQAAABhBKoqSCpmO6pLIjBokwga14onc/XOkRZ9WPKfFf/d0Aq6HOjL5Vm4ZxxRP3
+mjyLI/flOjrx5aMVAed5xkX6shh+zN4mb2xajuPTwqbvsVvIyglrFbKKQO3DQnkbbeqBHL
+PAAAAOCTdP9vi3Go06Z/wni2pxYNgJK9V8nFfmVceblZYMdAfP0WFAKK/i84Nodl2t72g0
+xAkCOimLPGI7xHL6ZVPe6IOzvaW3wx7L8DSXfoqhKLzJwPVG+iH1m4AyUTU7osswSHzVHv
+nZsU+HPcetVahWWfbswLB4hjbyoQpxc2B0qk0UQJ8E1FsPpjMcpgHOtKEWrmbpHChSI9p3
+KyVGlMtL9CII0hTu61KKm1AgcX+WykIFLjqTpG2PY2X/uuW56nhYrDJqPXL4CPYTwxTRCN
+MOV9toMiqAQHz1JqadMsbdviEQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key.pub
new file mode 100644
index 000000000..3ea1b8e5b
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ecdsa-psw.key.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBKoqSCpmO6pLIjBokwga14onc/XOkRZ9WPKfFf/d0Aq6HOjL5Vm4ZxxRP3mjyLI/flOjrx5aMVAed5xkX6shh+zN4mb2xajuPTwqbvsVvIyglrFbKKQO3DQnkbbeqBHLPA== ecdsa-psw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key
new file mode 100644
index 000000000..34565dbf8
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACDdZgztgAFFC7T5PifrUy/kMu0Pnwq1au3vStKHe7FFMAAAAJhNWbUCTVm1
+AgAAAAtzc2gtZWQyNTUxOQAAACDdZgztgAFFC7T5PifrUy/kMu0Pnwq1au3vStKHe7FFMA
+AAAECQxzIh6s9TpOOlHcnFpjQIdZWmrhsU3eTq05iGHQejl91mDO2AAUULtPk+J+tTL+Qy
+7Q+fCrVq7e9K0od7sUUwAAAAEWVkMjU1MTktbm9wc3cua2V5AQIDBA==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key-cert.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key-cert.pub
new file mode 100644
index 000000000..b0240b366
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key-cert.pub
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJjE7jTtIuJ68m5zBEtn0bCWKUXcMdAOau0hO3FTMpeAAAAAIN1mDO2AAUULtPk+J+tTL+Qy7Q+fCrVq7e9K0od7sUUwAAAAAAAAAAAAAAABAAAABG5hbWUAAAAAAAAAAAAAAAD//////////wAAAAAAAABkAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIN1mDO2AAUULtPk+J+tTL+Qy7Q+fCrVq7e9K0od7sUUwAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEAqewM0LFjD4qQUdGNmF/W512ogcjh5xDchw9h2GjhFstttkQVfEOATyafZ5/vWGegMjSnGWHHTxv1A5bqzA+UE ed25519-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key.pub
new file mode 100644
index 000000000..21ead3741
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-nopsw.key.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN1mDO2AAUULtPk+J+tTL+Qy7Q+fCrVq7e9K0od7sUUw ed25519-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key
new file mode 100644
index 000000000..f1c756378
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCX39wD02
+J9++SP9d3vlnxuAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIFpz5PWWlJVx/imA
+hJjv57fg4eTGFVHf4WcFfbXPNo+/AAAAoM+Bu9OvuVW6elNfhl4AxM/p7Oy02ptuWR+LNV
+Y9Sjp/ADM+aTHb77DbZFD8WqzXhioUcOcej1EdAr4NFP7YRC1TIDHuzKgePDjewMMK7lCw
+9qZgZbBUYN8q0/V42L9Tc9w8rjkewtd6r5u+5UOLv7Ct7WxSESAAC1KC5TnnU0CCZ1ZFXN
+NOsxE0VLn5e+SDyILFF8fGt3mGk0S1D50zVzY=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key.pub
new file mode 100644
index 000000000..4c3d949e4
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/ed25519-psw.key.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpz5PWWlJVx/imAhJjv57fg4eTGFVHf4WcFfbXPNo+/ ed25519-psw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/gen.sh b/vectors/cryptography_vectors/asymmetric/OpenSSH/gen.sh
new file mode 100755
index 000000000..b18c338b3
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/gen.sh
@@ -0,0 +1,62 @@
+#! /bin/sh
+
+rm *.key *.pub
+
+# avoid having too many files
+ecbits="ecbits.txt"
+echo 521 > "$ecbits"
+getecbits() {
+ last=$(cat $ecbits)
+ case "$last" in
+ 256) last=384;;
+ 384) last=521;;
+ 521) last=256;;
+ esac
+ echo $last > "$ecbits"
+ echo $last
+}
+
+genkey() {
+ fn="$1"
+ args="-f $fn -C $fn"
+ case "$fn" in
+ ecdsa-*) args="$args -t ecdsa -b $(getecbits)" ;;
+ rsa-*) args="$args -t rsa" ;;
+ dsa-*) args="$args -t dsa" ;;
+ ed25519-*) args="$args -t ed25519" ;;
+ esac
+ password=''
+ case "$fn" in
+ *-psw.*) password="password" ;;
+ esac
+ ssh-keygen -q -o $args -N "$password"
+}
+
+# generate private key files
+for ktype in rsa dsa ecdsa ed25519; do
+ for psw in nopsw psw; do
+ genkey "${ktype}-${psw}.key"
+ done
+done
+
+# generate public key files
+for fn in *.key; do
+ ssh-keygen -q -y -f "$fn" > /dev/null
+done
+
+rm -f "$ecbits"
+
+# generate public key files with certificate
+ssh-keygen -q -s "dsa-nopsw.key" -I "name" \
+ -z 1 -V 20100101123000:21090101123000 \
+ "dsa-nopsw.key.pub"
+ssh-keygen -q -s "rsa-nopsw.key" -I "name" \
+ -z 2 -n user1,user2 -t rsa-sha2-512 \
+ "rsa-nopsw.key.pub"
+ssh-keygen -q -s "ecdsa-nopsw.key" -I "name" \
+ -h -n domain1,domain2 \
+ "ecdsa-nopsw.key.pub"
+ssh-keygen -q -s "ed25519-nopsw.key" -I "name" \
+ -O no-port-forwarding \
+ "ed25519-nopsw.key.pub"
+
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key
new file mode 100644
index 000000000..9d755e818
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key
@@ -0,0 +1,27 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAQEAq2QdSm22QEsm+GtpAwN4qk0exDIxwxUb8jJ6LLLo19KJR9ySQw+d
+Ajp9WIUumXM2OPYi0qqtN6JKMsDrVSR87RoK7V2W4lHYljZBODGYA8bfpqaLt5HMvkJpsk
+MEBqJkZtwO8G/J3QDOFByiGOxeeL4/2vnM5XwN/ff6SKABxfU60gDmlofFlZqCD9exWO52
+dg5BQ/gN5qJLBKBZmC3jWnAkrblvfPxwfp9WC3gMrFIILytCWvRu9YKM+nQZoqo0yCbzDy
+7GRK5XZJlHfw+jV3MWMSXS7GSirOmTtmyygCtkphA3Y8HAQlibhdg+5jZDWRdDXIU2uOET
+iHc8qvxM8wAAA8jQzBt60MwbegAAAAdzc2gtcnNhAAABAQCrZB1KbbZASyb4a2kDA3iqTR
+7EMjHDFRvyMnossujX0olH3JJDD50COn1YhS6ZczY49iLSqq03okoywOtVJHztGgrtXZbi
+UdiWNkE4MZgDxt+mpou3kcy+QmmyQwQGomRm3A7wb8ndAM4UHKIY7F54vj/a+czlfA399/
+pIoAHF9TrSAOaWh8WVmoIP17FY7nZ2DkFD+A3moksEoFmYLeNacCStuW98/HB+n1YLeAys
+UggvK0Ja9G71goz6dBmiqjTIJvMPLsZErldkmUd/D6NXcxYxJdLsZKKs6ZO2bLKAK2SmED
+djwcBCWJuF2D7mNkNZF0NchTa44ROIdzyq/EzzAAAAAwEAAQAAAQAYxAivfpb9R17EOtEb
+zF6dTTOK6i3ioKQ/JSgeWWPn+9Y2ehrwccsgTU9bgTMwnUNSi86QXnVVOrA6EUJwNSuQH1
+lA32s0HNuNKR3XfuMWeKBMtngt+HV7cKFRTvm/86tKabYG7EBhHQKqSVDrBQzJqcQUYlBH
+QNvMvQ5/fA+FiSN5RT/Hv0iJy9WFQyqN8W1KwWUnFnXgEw9ZFBlhjugcKDS1l+fyoDN0p8
+/Lm0ojn2I7I9SH9tXKb330zhO3CfXMVtjnpyi8wQALT6nEarfBwzGK6R0xWX3Xm+i2fQBb
+sIBDr5r3WWpQlnPnFx1lSntQeoUVLJEimRklQJVL41fhAAAAgG923QGfsC61Fp22Q+rVb8
+0N66qxCfnXnQDbtT7ZdFK7tjXdKVA/GU+vU/pgFarixYcGS5gDKbAJM2R6XLz9cE5UVzaw
+TrJab6bHG9bX8xh2kSKcY0GW1/QWp9pv6IWrCQziXiDP7uxDndxolfnHXsjT3QVfNQV+J8
+gtkjP3aCy1AAAAgQDZOcREo87MzWwbEoVAETZ8uVqWspTwJtAvIuqHePvHa1wvc5fWqr1Z
+1wUN/Wl/DKhOjydBXQSa/SfKdsIx0JRkia06bYvS1eoL08+y3aHFkIR+WOp6bVYH/p3HzH
+9qdMx7IHpAco7ZtBmQ4O2nZamVBRX5FnxkcmkCHccENSh9OwAAAIEAyfvp/f6ka1FH/mW0
+MqRxAhzB8SoUGbvnGhgBxTWgCH7iMbtUwVsi3TbJr0gYBYQoFH61rAGvOfUTb9cd9+bowR
+j9m3oBOwSJBJG25hrmsqyFuZQlSMAv/AXjjLNUF1AQkpRZZMcEd6rTffprogiwkGdrRTMe
++tjRZCCgQaN+06kAAAANcnNhLW5vcHN3LmtleQECAwQFBg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key-cert.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key-cert.pub
new file mode 100644
index 000000000..35b0c2bbb
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key-cert.pub
@@ -0,0 +1 @@
+ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgtL8iJdlD7w2obBZdlxyqu06uLR78fvDASlnR3RRk/eMAAAADAQABAAABAQCrZB1KbbZASyb4a2kDA3iqTR7EMjHDFRvyMnossujX0olH3JJDD50COn1YhS6ZczY49iLSqq03okoywOtVJHztGgrtXZbiUdiWNkE4MZgDxt+mpou3kcy+QmmyQwQGomRm3A7wb8ndAM4UHKIY7F54vj/a+czlfA399/pIoAHF9TrSAOaWh8WVmoIP17FY7nZ2DkFD+A3moksEoFmYLeNacCStuW98/HB+n1YLeAysUggvK0Ja9G71goz6dBmiqjTIJvMPLsZErldkmUd/D6NXcxYxJdLsZKKs6ZO2bLKAK2SmEDdjwcBCWJuF2D7mNkNZF0NchTa44ROIdzyq/EzzAAAAAAAAAAIAAAABAAAABG5hbWUAAAASAAAABXVzZXIxAAAABXVzZXIyAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQCrZB1KbbZASyb4a2kDA3iqTR7EMjHDFRvyMnossujX0olH3JJDD50COn1YhS6ZczY49iLSqq03okoywOtVJHztGgrtXZbiUdiWNkE4MZgDxt+mpou3kcy+QmmyQwQGomRm3A7wb8ndAM4UHKIY7F54vj/a+czlfA399/pIoAHF9TrSAOaWh8WVmoIP17FY7nZ2DkFD+A3moksEoFmYLeNacCStuW98/HB+n1YLeAysUggvK0Ja9G71goz6dBmiqjTIJvMPLsZErldkmUd/D6NXcxYxJdLsZKKs6ZO2bLKAK2SmEDdjwcBCWJuF2D7mNkNZF0NchTa44ROIdzyq/EzzAAABFAAAAAxyc2Etc2hhMi01MTIAAAEAC13gJgpzMrO3fGM7lNpLLBDUa6GxB4Lr/RSHLxG5v9+Ym7z5aIYmneYifbNQ9qIPDxpuBQvN97NgV4ImSMjfIaaQi/PxyHKC+mxMXAonT5c5d+zhZHQ95/uxIt6iba1ej3MRVYw+biQlnIHhOUeJNV3W8UOry0XQlJzjTBR2/1Y+Xk89NbZ3F6QQ9UZpT/FvbERghElBauTz1UhtSlMCrn66tEOGxreVHraoM92pJaygginwb5iVU0SPWhWG3Qyh8P6uKzqSKIr+6BfaiIoWJXOLLEtSfmuK8dTuE8fNeU4PQlkJBqfcWbpD934QsP1dXWhan5Y4iFMK4IjcPNu7iA== rsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key.pub
new file mode 100644
index 000000000..00c01e299
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-nopsw.key.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrZB1KbbZASyb4a2kDA3iqTR7EMjHDFRvyMnossujX0olH3JJDD50COn1YhS6ZczY49iLSqq03okoywOtVJHztGgrtXZbiUdiWNkE4MZgDxt+mpou3kcy+QmmyQwQGomRm3A7wb8ndAM4UHKIY7F54vj/a+czlfA399/pIoAHF9TrSAOaWh8WVmoIP17FY7nZ2DkFD+A3moksEoFmYLeNacCStuW98/HB+n1YLeAysUggvK0Ja9G71goz6dBmiqjTIJvMPLsZErldkmUd/D6NXcxYxJdLsZKKs6ZO2bLKAK2SmEDdjwcBCWJuF2D7mNkNZF0NchTa44ROIdzyq/Ezz rsa-nopsw.key
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key
new file mode 100644
index 000000000..cd1f38f3c
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key
@@ -0,0 +1,28 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABChvLeROo
+MQfWAC6b7jds47AAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQCek3p8wNo1
+5l7Ihy4yaGjWScJpjh/Lq7WS7f64KxXKodBe35fLl8lu9Ds4Y06XWeHZdGxC+qp4QoxGYI
+Ft2Awm8sz2wRbPY7d322tG9VnT59bQlvKtq77y9ZYefsdVwh2Uf7otdUZOEz6KuKc1CXXb
+FfBFY6YB1lZ4YkQ2YHsYau22RHDjaHi55VoFokyk7cVnuhaIXCrppAH5+AMoqVtrAb/48G
+2gGdQSo90heqglW7QLXPx2sCijp+62coXzbfViYzARdc5rbcih7zAfxEHMi+1HZmdvNKvd
+2Vy+jPFD+FvvHUDl58XChAjJVmgrsqbZanpgIDD4/48dSnHSH0OxAAADwOuiaWL5LLLt5D
+8bC7i0soG4LUSlwn0GlYhYyeMTBDswEcm+BGt+S1vgHO6f6oA+v+A/npxgwN7OrCJoq5Ls
+iJZ//KCB+GCXXF0wXldwFcNtMoylG2FVo8Gx+Jckm+wSy+Uk73Sk+D+4UiHNGeFuQ85PbX
+ceyne4iayry3PkiWHkfCVUy2UgW2L3YKtoDfXZ5QK3JVPxfMvQnDnP47r3L48rVCfvYVVy
+SX+YnKgwMJPa4DX6mF8E6MPtntzZoN2MUwIJRlRZl1KqzmsIKl/XWsxsQuosvMT1wdDGIf
+uT3uVtabeMyybM4tzPwXdzgnh9Mv2PmcOV15XCmxBFQP81yB8AkuUTWuekEbgypIvppQiL
+vlmiSdWsAZvBqYN7lpuIJloRH3PCyzKSBLDJ6gSpb+ysX9s+Z2of3arBo0wAipZzl+S65R
+guK7IxZu4fynOKojRjL97w6FN0GpaMOC0QiDNfSIg3wk3FJ8c6DFRjKDgaXSk90aMNEGLX
+kOidZ3lQJI3K3KODDt28F9mKfOS6lyUWe9+4CQO+oJkY9EdUgiT3ZSbbQAWjCGSh4A6/Z8
+VHKYb7UCBHYf431VF95yY+2u31Amr76iHuhVZ+G5tcwytvHjuheZQttXSkvvst7J5fxPBT
+kLXfm75RUH9ajveDR9mZq4SmJzlOHPkAn8qZ6QeLGvtsp0Lde8dKu6bo2eqtilbVMr6fi1
+9U+il6J+K+DiAcMh1vOAp0nhecstlabMN+NnENnWy2s+zyQYLKMUACYge7vWxbgJ0PFNkF
+8RM6vC8/IIP81VSp/ako1Dsjh26uhAF92/HHCkAgFiUeBXACjvDo8/FSFbdbutlyl4bvOE
+miKQfSLWqh5lxjDySYOzhGerAivmRCNUviseFTTGP/qE/+s0VZjuMt3afE4H/9baftyt+O
+Iz1OGaMKXPD40mWhj4LUdD+opzGtjexojUPCCzYMzKsEz+WFE3//TWmcM3jq6lSDwbgbVI
+82MGXf0htD7RtB9Gy3pE793LiRecCMygp/gF0ViPa6mwIxMOTy1mp0F5bCddRsNWGA91kF
+XcSjUo/1mpFADMgUcrEsUCK69oxl1D/hPrkvvGEG/U/6z0gS9/cTeIim/6wg+XSULNfOgG
+l0Ate1oHdrZ8XVjHq8e05L5VbYvXMvc9ETnB786kxAuJKc+60KPQS5KHZFiZEAvEcFnd7s
+vCjY0NEf8s8Ofn0jI50UiMn5Ge0YEhtypQOb11kawG1L9UIgL3HJsm7e8osYdGig3ejFHL
+teHHc5kg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key.pub b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key.pub
new file mode 100644
index 000000000..ad94f9594
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/OpenSSH/rsa-psw.key.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCek3p8wNo15l7Ihy4yaGjWScJpjh/Lq7WS7f64KxXKodBe35fLl8lu9Ds4Y06XWeHZdGxC+qp4QoxGYIFt2Awm8sz2wRbPY7d322tG9VnT59bQlvKtq77y9ZYefsdVwh2Uf7otdUZOEz6KuKc1CXXbFfBFY6YB1lZ4YkQ2YHsYau22RHDjaHi55VoFokyk7cVnuhaIXCrppAH5+AMoqVtrAb/48G2gGdQSo90heqglW7QLXPx2sCijp+62coXzbfViYzARdc5rbcih7zAfxEHMi+1HZmdvNKvd2Vy+jPFD+FvvHUDl58XChAjJVmgrsqbZanpgIDD4/48dSnHSH0Ox rsa-psw.key
diff --git a/vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem b/vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem
new file mode 100644
index 000000000..af14d247b
--- /dev/null
+++ b/vectors/cryptography_vectors/asymmetric/PEM_Serialization/dsa_4096.pem
@@ -0,0 +1,36 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIGVQIBAAKCAgEAy8x5LsdCM2fSykikHtoZZPXcZIRm6ZQQTdpkOHyX9AAqVVpc
+kXqUltbd1rLCPLrii/Syg1XBwsna7fUEci13xUHDk/97TLG9Z0qIH7NgdBQSFGTL
+GWLRbp83nE1Hc+/b0htaABTT5AV5q54xoDED8AuP1b2l7SxrgJz/uDsvZcmHM0y3
+AxTiFkPCqNM+nHN7w3A5NJmFlvm3pl/8B9DCvLXILqiFYpKwewa4f3RUIqCuKlgJ
+y1Yj5BtjiWzJV6153vuAuFaD86G7Pck6VQDEpaY8u0LrjAAgzjaUvD45uDgkw2HT
+/sJDAkIWjpyPEEvXNUmgC8Eh52GCeJkT5iG04a83k67VPbbS3dENRgzrfYpmRIlJ
+lfoxtIpFEkDT8jpioDIzven7JNIhNND0Y/bs3pxnkIjrs3jPGpW9dtoeP2RYSlle
+QGqhu/B8lIEpruy94/Ujz7nVYnNSHZGY/Xk2pLR78B1tzk/mojcgTGtq76GHuY4+
+p2I49qThgWOGBT8b9ysYgI2momHcDkauYDq+l0dLg6h6XPPsXU/8qHL2e5bCW1ub
+uMb0T4NwbLwl9rHc2gcKxfdqnK0S4hgfWR5nhDsLyBl04mBqnZaoQ/1Re5Kp1ZPU
+a8/CR0oktwh8ZP0TmUbExSd8s/kAUJl49Fp2EGxFX3pF2u+mucbd7iDLVzMCIQC8
+2B6GLZaBrH0OZX2UWz8A10CuSHAqib45GIwrcEqVawKCAgALNtzq+Ap3IPQrjnsv
+H9VLVoLx2X37UF6DQbX9ZMcnKNwooVNxkLPXokMIbVPcsegavw1ECgiCu/Ung+aM
+Whd5w4iMMxq82I9nd8M2GUvg2QYYz5WOLsbJTk1kcV0WF+MzMrWCAuXiuCfYj90X
+/TT4Dhd037fVfktjwzJFtox/NKKAM96/wm1MHfwy4s7L1cTe1IZZocZDB/4l9Ciw
+zNAc/VlNfmheAp2RlrdY2waHVCdU/AJt3SNghUqLAn5dJELKyY37Kl9OHxlnWhTl
+dTBzC6VFo4Gkro28/C2kY/PYkShEXPT1c8D63lbYdUt5dgnfkDpddjRvgXGLOltJ
+1/iogrMq2EKYECoXtNzM7xXu4vxMNERjbyuhWg9qw0mczFgel1R7UWeMAz5a7J5S
+fHs2p94/iyQZPHHzR4DEXC/dcuUer5koPJvdIO6hbqMtfcWEusOEdOxRapjrzaLN
+bCaL4c33j8y7FOK2JC+FAz4ljI9AIsomt73tyrRK0PFUrlh147cuOKZAGYHQJlaX
+z6R/W8z71vO00/VvIZuzHOYiGZQdQ9FUiilQfrhGTF+SOyjBMSSantUUVUoYRC7E
+Tc83vQEQnpe5VjX+naSCk/zv1JFGSSpmWn45aDSswmA9EjyKxg1Ae0MrshB8a80M
+eqRrfGtlLuGT0KiYKse9z90VTAKCAgBFBTIdD1g7KRadTcyhoXw5+zMv9vVb4kDx
+UAyuqPulh3xadD1FUMukQWjCzJDtx8xDSOj1U9Tal/DsUBtzS+MyPAQdsXhs4oYq
+ska/OWc8287dtX2U511de2bd5GS9rI++HKLHES9RBkAhuo7l5cc+TGJ8XeFgbmdF
+DStjyLy4ABLG0Fkk70nMHIIGal/axBz0kYhSf1W1XO2y2PAY8/sNwdHwI7TimEcL
+qxakgneBjLn7L+SO3N5IRI1eLwl/0sj6ZUoaV6ZpPuTNDTo+7PQlMP+OqIL77R/M
+2rsJSE186CI8IR99K7PylS2Gk+RWv6NcYnZCOcP4UdXEg7/cECjWaSKqn20q2Jrs
+ZuVrRoVF4XsHmcItYj8JyeFcGUgUSlPVNMvO9L11IMvvgo9EQ5OU0UHiBZRoWWu6
+GWx7VqqNU078z2jL+q8MFcqNzqXM64DtVDc1sjdZSLcNzKRWiMrnek4MB+aL1l7G
+hXdDRkj3qTRrkvzHBfxDm2u4lpMInFci1Lu0oxgqLEISYAGdyb1we+OMeqR12YUr
+QP5/DtJdntE0hKMIWGkAYHvIowu2ZOUPs6mdgJZ/IL3qJsvLG2ZFpe3aBnbL8qj7
+/ezCts5E509IwRiVhvEik6ZKUjSYojkcWL88p4PGZsP1/iG8KQgMnCrPIOjYVTVM
+Qs3D7GFsYAIgAhium9LrIx3luKDOsxS4nX9f8xChr+Z1Ej8xgaqp96Y=
+-----END DSA PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/ciphers/Blowfish/bf-cbc.txt b/vectors/cryptography_vectors/ciphers/Blowfish/bf-cbc.txt
index 184d9565f..ad3fa0cf2 100644
--- a/vectors/cryptography_vectors/ciphers/Blowfish/bf-cbc.txt
+++ b/vectors/cryptography_vectors/ciphers/Blowfish/bf-cbc.txt
@@ -1,4 +1,4 @@
-# Reformatted from https://www.schneier.com/code/vectors.txt
+# Reformatted from https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
# to look like the NIST vectors
[ENCRYPT]
diff --git a/vectors/cryptography_vectors/ciphers/Blowfish/bf-cfb.txt b/vectors/cryptography_vectors/ciphers/Blowfish/bf-cfb.txt
index 8a326f500..cd2f58ff9 100644
--- a/vectors/cryptography_vectors/ciphers/Blowfish/bf-cfb.txt
+++ b/vectors/cryptography_vectors/ciphers/Blowfish/bf-cfb.txt
@@ -1,4 +1,4 @@
-# Reformatted from https://www.schneier.com/code/vectors.txt
+# Reformatted from https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
# to look like the NIST vectors
[ENCRYPT]
diff --git a/vectors/cryptography_vectors/ciphers/Blowfish/bf-ecb.txt b/vectors/cryptography_vectors/ciphers/Blowfish/bf-ecb.txt
index bb18a5a3f..70c1c0308 100644
--- a/vectors/cryptography_vectors/ciphers/Blowfish/bf-ecb.txt
+++ b/vectors/cryptography_vectors/ciphers/Blowfish/bf-ecb.txt
@@ -1,4 +1,4 @@
-# Reformatted from https://www.schneier.com/code/vectors.txt
+# Reformatted from https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
# to look like the NIST vectors
[ENCRYPT]
diff --git a/vectors/cryptography_vectors/ciphers/Blowfish/bf-ofb.txt b/vectors/cryptography_vectors/ciphers/Blowfish/bf-ofb.txt
index 21a742184..f87609a99 100644
--- a/vectors/cryptography_vectors/ciphers/Blowfish/bf-ofb.txt
+++ b/vectors/cryptography_vectors/ciphers/Blowfish/bf-ofb.txt
@@ -1,4 +1,4 @@
-# Reformatted from https://www.schneier.com/code/vectors.txt
+# Reformatted from https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt
# to look like the NIST vectors
[ENCRYPT]
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_224LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_224LongMsg.rsp
index 7eb3e5b77..7eb3e5b77 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_224LongMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_224LongMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_224Monte.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_224Monte.rsp
index 14eb09713..14eb09713 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_224Monte.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_224Monte.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_224ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_224ShortMsg.rsp
index 1a903e355..1a903e355 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_224ShortMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_224ShortMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_256LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_256LongMsg.rsp
index 4ed57e7d4..4ed57e7d4 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_256LongMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_256LongMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_256Monte.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_256Monte.rsp
index 139a876a9..139a876a9 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_256Monte.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_256Monte.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_256ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_256ShortMsg.rsp
index 34fb8c7ac..34fb8c7ac 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_256ShortMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_256ShortMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_384LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_384LongMsg.rsp
index 33de8707f..33de8707f 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_384LongMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_384LongMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_384Monte.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_384Monte.rsp
index e3bd17d59..e3bd17d59 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_384Monte.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_384Monte.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_384ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_384ShortMsg.rsp
index 491c5dbc5..491c5dbc5 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_384ShortMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_384ShortMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_512LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_512LongMsg.rsp
index 5e56cb7fe..5e56cb7fe 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_512LongMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_512LongMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_512Monte.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_512Monte.rsp
index cc2432ab6..cc2432ab6 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_512Monte.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_512Monte.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHA3/SHA3_512ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHA3/SHA3_512ShortMsg.rsp
index 37ed20d45..37ed20d45 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHA3/SHA3_512ShortMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHA3/SHA3_512ShortMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128LongMsg.rsp
index f39a5a6f7..f39a5a6f7 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128LongMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128LongMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128Monte.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128Monte.rsp
index 521175ac7..521175ac7 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128Monte.rsp
+++ b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128Monte.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128ShortMsg.rsp
index dd4130e6d..dd4130e6d 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128ShortMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128ShortMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128VariableOut.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128VariableOut.rsp
index 6251eb565..6251eb565 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128VariableOut.rsp
+++ b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE128VariableOut.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256LongMsg.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256LongMsg.rsp
index 1faa2f8a7..1faa2f8a7 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256LongMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256LongMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256Monte.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256Monte.rsp
index dea7a1fd1..dea7a1fd1 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256Monte.rsp
+++ b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256Monte.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256ShortMsg.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256ShortMsg.rsp
index c4926b6fd..c4926b6fd 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256ShortMsg.rsp
+++ b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256ShortMsg.rsp
diff --git a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256VariableOut.rsp b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256VariableOut.rsp
index ad5de4607..ad5de4607 100755..100644
--- a/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256VariableOut.rsp
+++ b/vectors/cryptography_vectors/hashes/SHAKE/SHAKE256VariableOut.rsp
diff --git a/vectors/cryptography_vectors/pkcs7/amazon-roots.p7b b/vectors/cryptography_vectors/pkcs7/amazon-roots.p7b
new file mode 100644
index 000000000..cb027da5a
--- /dev/null
+++ b/vectors/cryptography_vectors/pkcs7/amazon-roots.p7b
Binary files differ
diff --git a/vectors/cryptography_vectors/pkcs7/enveloped.pem b/vectors/cryptography_vectors/pkcs7/enveloped.pem
new file mode 100644
index 000000000..7c7d5b75c
--- /dev/null
+++ b/vectors/cryptography_vectors/pkcs7/enveloped.pem
@@ -0,0 +1,91 @@
+-----BEGIN PKCS7-----
+MIIQjQYJKoZIhvcNAQcDoIIQfjCCEHoCAQAxggLCMIIBXQIBADBFMC0xKzApBgNV
+BAMTIlNhbXBsZSBMQU1QUyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkCFCJT7jBtAgsf
+As31ycE+Ot95phvCMA0GCSqGSIb3DQEBAQUABIIBAFbDR6j4ZB/Mo9BQygYItwFc
+P+4rO4d1ak51hc1DpSqyhiMcGahA3yxDRbZ4W1rbmC/s3d5+OWXKYgs1nNMQJ48F
+f45BtNTNslPZ1+NZVbkoVJO8Bxv1rjB8/qWuSUsroqzn9enS8DUBxxPL5aSWKQQN
+G2IaH9BUkMXLPUYA46GATly94IS4fZqwBtNNBP5eiIIPc9Ogjy+7At5GG7rVMN0M
+G5FL0oq52SYUe1167jp378JI+2dkA1q5+Cru/ZE2Rdw3DrMDAFO5GwC7fWKg4zPm
+IHZj92caVj1IyfTmGogT2o5tLMqn61BkptqxZwHDr3FI/aYo4vcHgmlKR/TdbHww
+ggFdAgEAMEUwLTErMCkGA1UEAxMiU2FtcGxlIExBTVBTIENlcnRpZmljYXRlIEF1
+dGhvcml0eQIUZ4K0WXNSS8H0cUcZavD9EYqqTAswDQYJKoZIhvcNAQEBBQAEggEA
+hXeYVSUsT1EBZ/+AjwyEcnlM0kuFMaNvGlBMhAZzAsy012rrZTWbqWkcA3abgm/M
+CuZX7mQL0I79KZdmClGpLx6gQFjLemHaClQV0ZNdX4DxakWuME/kCMqbo4MZXStT
+a0MHlKUdoMt72Rz4YBzNQCL7ePaii5w6Nd2KD7yJAirLYUMJEjVweVaMI9y9LmbO
+vb0g0iuoUe0vp9B20LRcIX37nN5D1GG4tHLPjBD43gC8iqxZQf0uah2cWD1mAG5R
+oBgIDKXPy2eVbcMdSaOirDKYZ49WFe9Lad9q3mHHbFs6K6/yuBm/thMEdCJKZTHo
+jiPvYdYF8IJfEd368I+DujCCDa0GCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIsb1a
+JX/RU9aAgg2I0VXWfs5fc/Yad2qvawUVNX+LObjA6/+t9WxuV2emOeBYzQGjo7q+
+xaIXQwbbF1ej27efGhxUYDwBNS56c0uI0Ta7jxv5OFZhzQGLRzoFp0bbZ+uVC4eP
+bFHarRQiPzlg900XASO0RW+UOtqN5raZ3Ry2lKwXxuStZ0pX666Rz4c8PrmMb4/B
+aQYn6iKcT6fDU2TpSbWY9iph6kZczSeewK+pIj9nXfjDKXScs8D2Raezev2ciq/V
+ZRpRH8JxieimI2yeBmEzTCq11TDYycDfMHB6reGaiCGX//8kAWtskzRyNlV61unY
+ZKSNhVKLwKmCQh1V1Nd3oLApT41EeM2oWedUqNBYqB+XGCD4DUYdm1e+4h73d4dn
+JTkCdadxEn+9RRvZ4YMlw3mvT997Dy3rTXT29dj14TstZZf2O63pY0TpYy0HZy6Z
+Jug1qoe/vdcJ9SPOSfJE6VWCeVjxB+eGgheFLKqzK8Hs/Bm0/wDKpSFgEpOPnkJ4
+HJ2Uzgn1Emo6gBDJt+qn3s2UnowcMsTgellhKvgzVq59LTyRyWL5U8XMBsXT4qjm
+0LkRvDkOIjMQH7kqvWbpPlnWpLKo/VVoxifldEegWAqFVrP7f5Y+nNQttAYV79uk
+MXvR+5YFkvmQAerfllPqXBJdbB65ovikSVsy/kAboGpRG1oAZ4ODdwdGyiGIzyyc
+lE0x/8+gY8BqWzRtWX4GySKyZ50/+xkJe5ss0IXPCgq/09bdihsRn57v4V4SpdDO
+k3g/Dce+LzCRL8uTbUhrhZnjKSjRc3fFaD/BpLYjEDbnGF0ICslN3vb2xWUK1u4M
+uUH9r7lH/DCb0+TxIBtxOnP7W02bz8gGJAxEVEqk6pjxxOYqfS9/uBrrAY8P21Y9
+PFLdeHzEdYemq3il+4S7OU3uNUuAYijxmCRs7JQxZ9puA0iaTME9gK1yikzsLtVZ
+f+9osk2nYgfXvlL0AiYabd5cU2GNW33TkdDMNBsB7lx77J9erVLZpPKNo4vgHA7b
+owrDaYe0AgcZm79fvmR0RdtIZI91MouEhkdhaPiXmypmszjR/M0Ot3Y+oU/ks+yV
+Sle0S0h4V8wJRJYG/9VVurm8012ke2U3EGFlVnSv/IYtpssC+U4McRCmakKCrGU7
+OhL5JKBQN/DFTu4pV39IQlLLhg3wzA2FSkyIL5gEbS6sP9GTPo5LlNm2nYfJQX9A
+sHKSrfh68dvjSNExxi/8hdmFnnRwbAnUCI/WObGOkKdheOfdQ1AAHtLO7G65X1Cx
+RctbAJWa93M+iRUN6qnB+vIbPPnI1Mc7i6mPYzgtPrM9bYqEZz69pQtHcGTfxOrU
+tm+/h36CRzJBfXodBZbwQ9mZAzfkKdlArlZYIeBUw3ORQnQ7UlJgG8KsZpUhTxCc
+gvMoExtlvkXcYLRUBFfZWyOi6FePzQjuCK1w58OdweJgXprEAWSvyxhmVdg4jUpX
+MYKE0tZI9xwujyWjACO0myYqTdmsqyds+BgfBn96XiA9OFUH2C0/GAomhNs8uPSO
+T3Gt7Ld/FByxEVrtl9A37X6bAwZO01j5tHmdXFPmMVep0R8zsWtPn3RyGAjcgcq6
+50wJRwhvofdI7wilZ0KUBsAaPj3MK52cRyD19VXKNNwt2bLDV6gcWQ8+QEMusxfp
+1Dc9N9DSs+w3lGsFfpoeQ53/fXcVNJm6Bv89bH9anLGYdCdRGvZsvw+xRuglykqb
+xLtL2lB6wzlRFREJoWTzCVsdpIZ8znPmk1cB0wDlbMeu6sddHmv+6fpyuvQfQmdj
+D8WLRTuyxax94TmBlhJCFYxmO/y4Ivlx5C60GIRTkHpBYL/M0RjrbIszXEqcogzU
+bdwjLIhdEnpJ5vy0uXwhltce8BDpenmHE7y1kHvPBiUG3vB7AIXqhohFsJU3AYUj
+d1TvFKS2AsizUTLuq0Ydbnz3AxMfmnZe8qYkNu2zRygL2xTa58f/MwsHKakk3OmS
+9JFZLrkkVWZKXoARctuahYtWBAsykaWVNnB6zGcdX1MGVccl930Z6QWHyydtZpQc
+ivNdEGdGv9B0K7/ngNdVgD5Wd29AMMFnS8+55mLfRZDCjUmshSySaf6Ein4HD9Hr
+vk6dJvBPjnI5UjeUPjmH+wcZKIjLHW/aV/6/zoxzBh61rWFlr/daec+CFZE/+epr
+LRRYSmv8oY47fF4duDDhoexcvP/CH+A2Hr40OfciL4vKy3nuUDCNa59xO9JWv4NL
+n3MQypC9bcaVPkXa7TK3ECq1Jgv8gwfdh5/ovG5OdZA4uIcO+aqcskt/PD252c63
+0Znww3RXXf46KT4GdKO5A377ixkUMkznnCMvottmkPxjnhQjAsQg3bJeQk8EoX8f
+Pq0If4i7SRBSDtb2OH1pPmk0RVPtxlRDTVj3vS3Lci4xADFgC09n9nIvPO/55aau
+O6StbJtLmpubS5giuDH3uftwuyRiLqm3gtbSKPdoTk+dJhHXbbpBknL4XYTPxSsR
+IIaRds6w30vf7/IscyunMcquJlsO929SSa93UevKEIZbqbV9oGIqwkiUMdVZK09g
+rW0F//Ts4a5nYdEQth/fq3JnwqeHvvUfKdasK4TtrTnUBX7qZk/K3Y1fZwjKdd/8
+t9t1z7Kb2d9hWwtY7xP8liDluVFTsq8NM54ZC2218X5ViWz1yFmF2LXvRixsmYJv
+Tz8lUUnC2B/Etm1kkU4zrYK0/L77EikKVl+B7BXfEqx6ow41j7e1YZYaqmZ9mph+
+UieSdzqVYxhPwT25DrkU3r74iS28gKsbFhUaNklaFOO5iDWsKgBXT+wdZqlYQ6Fo
+oPe66025iJMwK8t+d53jEduHezHO2sTMAuf2hpdaZo7+rP/hRTReAR6CmI7nkWhP
+z5Kno9S+XhiSP+WTSpsoA4ubx0T94mL8NOVvSZA76TZ3ObVAP5VI/bwv6Grighor
+Kpsjt7dhSJRv+RHv95sAWBeW1Fgv8XOPSAZOmpJV2qc3x3Qmj0MXIR+7+3GlUr8+
+Dit3CE1hwtxgOW0tc8kuBTfQD+wNSa9r0eUyFscEBBljpEVbLjgjVdNv4Hc+fsbT
+g1JzZuUIDQZoEO2xLjxD+I7vLZKQa0J1JeZ7O+NqmSxsvSnwCWtJEWNMMxYNfwsP
+rdj1zPLqn3rzSBqhroNbaDGn86BTwIqfhr+AKbvevxS6bI8IbyKm9u3BFr9cuawx
+Sp1QM3NtqNStV67qR4A6U/ZyPUJdO1bxo8F3oRmJqOt7Jc93rFgkhBJ2+eMtrA75
+Om5tB9LBVSl5U5yLP0COO1QE5pqk5yuhJLT9Dyss8bWDRbSWKj83e4YXhPnq71Bm
+001czylLVNUlDc69Tf7FXjtIxh2yjvOT3zeLBPXOjU0it+gAma4vgrh8/mMXnNiq
+OLsVow8aKqm+Ofd6m13K5riDFgXgNI9lbvPKUSWlEqDMEqXk1oAqD4Nb5NTGSFpQ
+Q4G+cHAxJCu7vcXBaZnP8uMP5IAkdg5jIPvvMRwg/aqkl/KbL98oYZ5+1xrOMuKA
+LT1uCJ4MMB0lWsa1He4jPe8LneSupw7vAXlbo2VzcOI6oCSY5hV+cGQRY+LjW81q
+Cu5nLq8bwgnZMSlPmwr0YrKmvh8YKyGOrmTadxykC5IC+XbrLDsw2Jd9mLIjUQ/V
+4ibjeb+e0QGob22WOplCLnHGW/SnYei8KG1dxs/ahS+8vQdrI880ZJx2QJnrz0Ej
+ux6tKv4mvUkqYA5hlTFeT3PTr54yA+YLcCLMfBDx4ykPQnYUBj7ONHuNSUYt1CJy
+faZ7cWAbhgH+wlTFdVBVeW5D4FRbM8dMTPXyfC5ygwTJOiDu3vQKyyDkmiX7sEaC
+P1JN2V55uacyR8ZAG5+Mlc4ZMx83kAIZZXTCdqa1EX8yda31FI2rDHmvW/82bmjL
+pvI4Nnn9+zzJtDVCJ0B2VAZ3Edov5GzPikm3un4+mvyhUZpH4sbT0+VhPCsr1+zn
+bDJyNw4AswxaaJKh2+7wBiU6h+9TP/lI8SAJHtZL7zHBH8tD10ptksLRWDs9vYqp
+/3T86S2vxJL5DvLFJSAZrYOE3InS+keGmTMCdAl9I8zIworC/8uQp0N8ESebEVjA
+aHotBk59lj/OW4JZ3tQkcdQWkpnUfW/x9xE2wthacHlRzYDDsFByjEqkQr0MU8VF
+EGij9RCC97zyFrhv0xJm1C6wX0pcuEcuPTNBf38WyBTIfmVHHz/I5YKk5cdWG7Hq
+fmccV5GKrs2BseR683HM+/u50sq0km9UrqjgFR1DjfDoRKp0guP9PqkJAnwG2nv1
+hmNtXumzkF0otP5LDKLJ84MGP8Wnb006iEdD48Lra+clRAIIuLX4A0wRQjViDp7n
+OByI6ZcQd4DTMHnFPRvMkNMLYn13LghD6P9TTjQZ0KCOCwmc2TMCIhJlvzOYX6Cc
+wJZYLO1ltgfnHEuh8ijv0u3d/BUpsknYKBSJGUyMEZ9iUtbFPVfXBGSTi3gcWHtl
+IrM7wjswJwHWSvZKWUs+YWWJTwj0apG6ViGllwOAqR9C48uLKgFWPbMoTpolnp69
+eiij5ZHxB0i7SI80D+r65b+fqaFzVIJXVEI0zu/mIilbYBnGkhLI/Naw1m2e1qVJ
+mi1JBjXLAT3pEJDh8b3Lpgw=
+-----END PKCS7-----
diff --git a/vectors/cryptography_vectors/pkcs7/isrg.pem b/vectors/cryptography_vectors/pkcs7/isrg.pem
new file mode 100644
index 000000000..63698aa11
--- /dev/null
+++ b/vectors/cryptography_vectors/pkcs7/isrg.pem
@@ -0,0 +1,33 @@
+-----BEGIN PKCS7-----
+MIIFngYJKoZIhvcNAQcCoIIFjzCCBYsCAQExADAPBgkqhkiG9w0BBwGgAgQAoIIF
+bzCCBWswggNToAMCAQICEQCCEM+w0kDjWURj4LtjgosAMA0GCSqGSIb3DQEBCwUA
+ME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNl
+YXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgxMB4XDTE1MDYwNDExMDQz
+OFoXDTM1MDYwNDExMDQzOFowTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVy
+bmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3Qg
+WDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1co
+HIe+3LffOJCMbjzmV6B493XCov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZsh
+ftEzPLpI9d1537O4/xLxIZpLwYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+
+lAOf00eXfJlII1PoOK5PCm+DLtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vr
+Fk/CjhFLfs8L6P+1dy70sntK4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6s
+hweU9GNx7C7ib1uYgeGJXDR5bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98fl
+AgeYjzYIlefiN5YNNnWe+w5ysR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81
+LygXbNKYwagJZHduRze6zqxZXmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1
+pzpRboY7nn1ypxIFeFntPlF4FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0
+544fAQjQMNRbcTa0B7rBMDBcSLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K2
+8Kh8hjtGqEgqiNx2mna/H2qlPRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdw
+iK1O5tmLOsbdJ1Fu/7xk9TNDTwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJ
+KoZIhvcNAQELBQADggIBAFUfWKm8sqhQ0Ayx2BppICcpCKxhdVyKbviC5Wkv1fZW
+S7m4cxBZ0yGXfudMcfuy0mCtOagL6hchVoXxUA5Z687gWem6yRXvhp2PhID25OmR
+kNwXm2IbRfBmldJ8b8LqO+8fz8vWrifxqbDIrv19fpr6IgTr/9l/6pErIrEXDo/y
+ijRbWNj8AclUubgmzIqIM4lMLYQ8gt/ullcFuiy798S3x047gr4xyCJzc5LRwoCk
+OTkQMyOCTDyfhrJVmB2+KYaMIpue4ms7VzqCcE3cCceJywoHTWzoXY7J786rx7u1
+K05F1krQJszlcsoIaqWV4xWh96TtySxfpfv/rCgCLr7Xe7vjcXuQFtMHXkZTfDcH
+QozTxJac1Zm1KuCVGoBIrkw5B87MR6RSlSu6uPut0jNTfeUdTW3VobHHQm/mQCc1
+XKMotweN540zkOcjn/tQnHlsRtW0FbOWbn6bDJY6uFItP9Zb4fsIwoT+JKijidqs
+auEYKrGoQ2Fb0x/cO4128i3ojXXfFzNsPVP7e8tBX//cotBhOOGWuKxdizfXddUz
+wJkRrp1BwXJ1hL4CQUJfZyRIlNGbJ74HP7m4T4F0UeF6t+2dI+K+4NUoBBM8MQOe
+3Xpsj8YHGMZ/3keOPyieBAbPpVQ0d73siZvpF0PfW9tf/o4eV6LNQJ1+YiLa3hgn
+MQA=
+-----END PKCS7-----
diff --git a/vectors/cryptography_vectors/poly1305/rfc7539.txt b/vectors/cryptography_vectors/poly1305/rfc7539.txt
new file mode 100644
index 000000000..9ad13a569
--- /dev/null
+++ b/vectors/cryptography_vectors/poly1305/rfc7539.txt
@@ -0,0 +1,56 @@
+# These vectors converted into NIST form from RFC 7539
+
+COUNT = 0
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+MSG = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+TAG = 00000000000000000000000000000000
+
+COUNT = 1
+KEY = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e
+MSG = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
+TAG = 36e5f6b5c5e06070f0efca96227a863e
+
+COUNT = 2
+KEY = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000
+MSG = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
+TAG = f3477e7cd95417af89a6b8794c310cf0
+
+COUNT = 3
+KEY = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
+MSG = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e
+TAG = 4541669a7eaaee61e708dc7cbcc5eb62
+
+COUNT = 4
+KEY = 0200000000000000000000000000000000000000000000000000000000000000
+MSG = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+TAG = 03000000000000000000000000000000
+
+COUNT = 5
+KEY = 02000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+MSG = 02000000000000000000000000000000
+TAG = 03000000000000000000000000000000
+
+COUNT = 6
+KEY = 0100000000000000000000000000000000000000000000000000000000000000
+MSG = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11000000000000000000000000000000
+TAG = 05000000000000000000000000000000
+
+COUNT = 7
+KEY = 0100000000000000000000000000000000000000000000000000000000000000
+MSG = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE01010101010101010101010101010101
+TAG = 00000000000000000000000000000000
+
+COUNT = 8
+KEY = 0200000000000000000000000000000000000000000000000000000000000000
+MSG = FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+TAG = FAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+
+COUNT = 9
+KEY = 0100000000000000040000000000000000000000000000000000000000000000
+MSG = E33594D7505E43B900000000000000003394D7505E4379CD01000000000000000000000000000000000000000000000001000000000000000000000000000000
+TAG = 14000000000000005500000000000000
+
+COUNT = 10
+KEY = 0100000000000000040000000000000000000000000000000000000000000000
+MSG = E33594D7505E43B900000000000000003394D7505E4379CD010000000000000000000000000000000000000000000000
+TAG = 13000000000000000000000000000000
diff --git a/vectors/cryptography_vectors/x509/custom/ca/rsa_ca.pem b/vectors/cryptography_vectors/x509/custom/ca/rsa_ca.pem
new file mode 100644
index 000000000..089bcce10
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/ca/rsa_ca.pem
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIExzCCAq+gAwIBAgIJAOcS06ClbtbJMA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNV
+BAMMD2NyeXB0b2dyYXBoeSBDQTAeFw0yMDA5MTQyMTQwNDJaFw00ODAxMzEyMTQw
+NDJaMBoxGDAWBgNVBAMMD2NyeXB0b2dyYXBoeSBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANBIheRc1HT4MzV5GvUbDk9CFU6DTomRApNqRmizriRq
+m6OY4Ht3d71BXog6/IBkqAnZ4/XJQ40G4sVDb52k11oPvfJ/F5pc+6UqPBL+QGzY
+GkJoubAqXFpI6ow0qayFNQLv0T9o4yh0QQOoGvgCmv91qmitLrZNXu4U9S76G+Di
+GST+QyMkMxj+VsGRsRRBufV1urcnvFWjU6Q2+cr2cp0mMAG96NTyIskYiJ8vL03W
+z4DX4klO4X47fPmDnU/OMn4SbvMZ896j1L0J04S+uVThTkxQWcFcqXhX5qM8kzcj
+JUmybFlbf150j3WiucW48K/j7fJ0x9q3iUo4Gva0coScglJWcgo/BBCwFDw8NVba
+7npxSRMiaS3qTv0dEFcRnvByc+7hyGxxlWdTE9tHisUI1eZVk9P9ziqNOZKscY8Z
+X1+/C4M9X69Y7A8I74F5dO27IRycEgOrSo2z1NhfSwbqJr9a2TBtRsFinn8rjKBI
+zNn0E5p9jO1WjxtkcjHfXXpLN8FFMvoYI9l/K+ZWDm9sboaF8jrgozSc004AFemA
+H79mmCGVRKXn1vDAo4DLC6p3NiBFYQcYbW9V+beGD6srsF6xJtuY/UwtPROLWSzu
+CCrZ/4BlmpNsR0ehIFFvzEKjX6rR2yp3YKlguDbMBMKMpfSGxAFwcZ7OiaxR20UH
+AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBADSveDS4
+y2V/N6Li2n9ChGNdCMr/45M0cl+GpL55aA36AWYMRLv0wip7MWV3yOj4mkjGBlTE
+awKHH1FtetsE6B4a7M2hHhOXyXE60uUdptEx6ckGrJ1iyqu5cQUX1P+VnXbmOxfF
+bl+Ugzjbgirx239rA4ezkDRuOvKcCbDOFV/gw3ZHfJ/IQeRXIQRl/y51wcnFUvFM
+JEESYiijeDbEcY8r1/phmVQL0CO7WLMmTxlFj4X/TR3MTZWJQIap9GiLs5+n3QiO
+jsZ3GuFOomB8oTebYkXniwbNu5hgLP/seRQzGA7B9VDZryAhCtvGgjtQh0eW2Qxt
+sgmDJGOPKnKT3O5U0v3+IPLEYpe8JSzgAhhh6H1rAJRUNwP2gRcO4eOUJSkdl218
+fRNT0ILzosuWxwprER9ciMQF8q0JJKMhcfHRMH0S5mWVJAIkj68KY05oCy2zNyYa
+oruopKSWXe0Bzr40znm40P7xIkui2BGQMlDPpbCaEfLsLqyctfbdmMlxac/QgIfY
+TltrbqmI3MNy5uqGViGFpWPCB+kD8EsJF9nlKJXlu/i55qgUr/2/2CdeWlZDBP8A
+1fdzmpYpWnwhE0KobzLS2z3AwDxiY/RSWUfypLZA0K/lpaEtYB6UHMDZ0/8WqgZV
+gNucCuty0cA4Kf7eX1TlAKVwH8hTkVmJc2rX
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/custom/ca/rsa_key.pem b/vectors/cryptography_vectors/x509/custom/ca/rsa_key.pem
new file mode 100644
index 000000000..97e39a501
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/ca/rsa_key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDQSIXkXNR0+DM1
+eRr1Gw5PQhVOg06JkQKTakZos64kapujmOB7d3e9QV6IOvyAZKgJ2eP1yUONBuLF
+Q2+dpNdaD73yfxeaXPulKjwS/kBs2BpCaLmwKlxaSOqMNKmshTUC79E/aOModEED
+qBr4Apr/daporS62TV7uFPUu+hvg4hkk/kMjJDMY/lbBkbEUQbn1dbq3J7xVo1Ok
+NvnK9nKdJjABvejU8iLJGIifLy9N1s+A1+JJTuF+O3z5g51PzjJ+Em7zGfPeo9S9
+CdOEvrlU4U5MUFnBXKl4V+ajPJM3IyVJsmxZW39edI91ornFuPCv4+3ydMfat4lK
+OBr2tHKEnIJSVnIKPwQQsBQ8PDVW2u56cUkTImkt6k79HRBXEZ7wcnPu4chscZVn
+UxPbR4rFCNXmVZPT/c4qjTmSrHGPGV9fvwuDPV+vWOwPCO+BeXTtuyEcnBIDq0qN
+s9TYX0sG6ia/WtkwbUbBYp5/K4ygSMzZ9BOafYztVo8bZHIx3116SzfBRTL6GCPZ
+fyvmVg5vbG6GhfI64KM0nNNOABXpgB+/ZpghlUSl59bwwKOAywuqdzYgRWEHGG1v
+Vfm3hg+rK7BesSbbmP1MLT0Ti1ks7ggq2f+AZZqTbEdHoSBRb8xCo1+q0dsqd2Cp
+YLg2zATCjKX0hsQBcHGezomsUdtFBwIDAQABAoICAQDH6YQRvwPwzTWhkn7MWU6v
+xjbbJ+7e3T9CrNOttSBlNanzKU31U6KrFS4dxbgLqBEde3Rwud/LYZuRSPu9rLVC
+bS+crF3EPJEQY2xLspu1nOn/abMoolAIHEp7jiR5QVWzXulRWmQFtSed0eEowJ9y
+qMaKOAdI1RRToev/TfIqM/l8Z0ubVChzSdONcUAsuDU7ouc22r3K2Lv0Nwwkwc0a
+hse3NEdg9JNsvs6LM2fM52w9N3ircjm+xmxatPft3HTcSucREIzg2hDb7K2HkOQj
+0ykq2Eh97ml+56eocADBAEvO46FZVxf2WhxEBY8Xdz4VJMmDWJFmnZj5ksZWmrX6
+U5BfFY7DZvE2EpoZ5ph1Fm6dcXrJFkaZEyJLlzFKehXMipVenjCanIPpEEUvIz+p
+m0QVoNJRj/GcNyIEZ0BCXedBOUWU4XE1pG4r6oZqwUvcjsVrqXP5kbJMVybiS6Kd
+6T8ve+4qsn3ZvGRVKjInqf2WI0Wvum2sTF+4OAkYvFel9dKNjpYnnj4tLFc/EKWz
+9+pE/Zz5fMOyMD9qXM6bdVkPjWjy1vXmNW4qFCZljrb395hTvsAPMsO6bbAM+lu6
+YcdOAf8k7awTb79kPMrPcbCygyKSGN9C9T3a/Nhrbr3TPi9SD9hC5Q8bL9uSHcR2
+hgRQcApxsfDRrGwy2lheEQKCAQEA/Hrynao+k6sYtlDc/ueCjb323EzsuhOxPqUZ
+fKtGeFkJzKuaKTtymasvVpAAqJBEhTALrptGWlJQ0Y/EVaPpZ9pmk791EWNXdXsX
+wwufbHxm6K9aOeogev8cd+B/9wUAQPQVotyRzCcOfbVe7t81cBNktqam5Zb9Y4Zr
+qu63gBB1UttdmIF5qitl3JcFztlBjiza2UrqgVdKE+d9vLR84IBRy3dyQIOi6C1c
+y37GNgObjx8ZcUVV54/KgvoVvDkvN6TEbUdC9eQz7FW7DA7MMVqyDvWZrSjBzVhK
+2bTrd+Pi6S4n/ETvA6XRufHC8af4bdE2hzuq5VZO1kkgH37djwKCAQEA0y/YU0b4
+vCYpZ1MNhBFI6J9346DHD55Zu5dWFRqNkC0PiO6xEMUaUMbG4gxkiQPNT5WvddQs
+EbRQTnd4FFdqB7XWoH+wERN7zjbT+BZVrHVC4gxEEy33s5oXGn7/ATxaowo7I4oq
+15MwgZu3hBNxVUtuePZ6D9/ePNGOGOUtdMRrusmVX7gZEXxwvlLJXyVepl2V4JV1
+otI8EZCcoRhSfeYNEs4VhN0WmfMSV7ge0eFfVb6Lb+6PCcasYED8S0tBN2vjzvol
+zCMv8skPATm7SopqBDoBPcXCHwN/gUFXHf/lrvE6bbeX1ZMxnRYKdQLLNYyQK9cr
+nCUJXuNM21tVCQKCAQBapCkFwWDF0t8EVPOB78tG57QAUv2JsBgpzUvhHfwmqJCE
+Efc+ZkE2Oea8xOX3nhN7XUxUWxpewr6Q/XQW6smYpye8UzfMDkYPvylAtKN/Zwnq
+70kNEainf37Q6qAGJp14tCgwV89f44WoS7zRNQESQ2QczqeMNTCy0kdFDn6CU2ZL
+YMWxQopTNVFUaEOFhympySCoceTOmm/VxX22iXVrg6XZzgAOeTO69s4hoFm4eoMW
+Vqvjpmi4wT6K1w2GjWEOMPDz6ml3rX2WkxCbu5RDA7R4+mM5bzBkcBYvImyGliGY
+ZSGlx3mnbZhlkQ3Tg+IESt+wnRM1Uk7rT0VhCUKxAoIBABWYuPibM2iaRnWoiqNM
+2TXgyPPgRzsTqH2ElmsGEiACW6pXLohWf8Bu83u+ZLGWT/Kpjg3wqqkM1YGQuhjq
+b49mSxKSvECiy3BlLvwZ3J0MSNCxDG0hsEkPovk0r4NC1soBi9awlH0DMlyuve+l
+xVtBoYSBQC5LaICztWJaXXGpfJLXdo0ZWIbvQOBVuv4d5jYBMAiNgEAsW7Q4I6xd
+vmHdmsyngo/ZxCvuLZwG2jAAai1slPnXXY1UYeBeBO72PS8bu2o5LpBXsNmVMhGg
+A8U1rm3MOMBGbvmY8/sV4YDR4H0pch4yPja7HMHBtUQOCxXoz/2LvYv0RacMe5mb
+F3ECggEAWxQZnT8pObxKrISZpHSKi54VxuLYbemS63Tdr4HE/KuiFAvbM6AeZOki
+jbiMnqrCTOhJRS/i9HV78zSxRZZyVm961tnsjqMyaamX/S4yD7v3Vzu1mfsdVCa2
+Sl+JUUxsEgs/G3Fu6I/0TsCSn/HgNLM8b3f8TDkbpnOqKX165ddojXqSCfxjuYau
+Szih/+jF1dz2/zBye1ARkLRdY/SzlzGl0cVn8bfkE0YEde7wvQ624Biy7r9i1o40
+7cy/8EQBR2FcXpOAZ7UgOqgGLNhXnd4FPsX4ldKOf5De8FErQOFirJ8pCUxFGr0U
+fDWXtBuybAb5u+ZaVwHgqaaPCkKkVQ==
+-----END PRIVATE KEY-----
diff --git a/vectors/cryptography_vectors/x509/custom/crl_delta_crl_indicator.pem b/vectors/cryptography_vectors/x509/custom/crl_delta_crl_indicator.pem
index f49da4c8b..d919c3706 100644
--- a/vectors/cryptography_vectors/x509/custom/crl_delta_crl_indicator.pem
+++ b/vectors/cryptography_vectors/x509/custom/crl_delta_crl_indicator.pem
@@ -1,11 +1,11 @@
-----BEGIN X509 CRL-----
-MIIBfTBnAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEmNyeXB0b2dyYXBo
-eS5pbyBDQRcNMDIwMTAxMTIwMTAwWhcNMzAwMTAxMTIwMTAwWqAWMBQwEgYDVR0b
-BAsCCQCrVKmM6x8K0jANBgkqhkiG9w0BAQsFAAOCAQEAUEE3Z8rgIZYo1YK0wZ2X
-bz9NnnE/X1YZQZ/IO/mSsz/k2d5XhLwa53zMlvX7J3UFEjEp+82b+gCMvgpJzTBq
-a/XnifnA8lnFJmPiLB1JgRm2/GsXxkws3ziH5D/6yRdV3MDRQzRg610GayF+LfrF
-74kMns0a1TaOfRhw1APiDvJLngElvcutBS3/mgr+SPPdDgFJ++PSrWOdAw4vo4HH
-TTxduelWWDag2Bg0L90Td8Cdv57jgbCjSwWPSLqfwq674cDxotYABqtLg1Q5jeg2
-GIzEZqYXWvxMc87pQLRwrxG2+U4p+hDpx3TTIn2uyxDTihXvWKmiqzpOiXJKixe5
-Jw==
+MIIBlDB+AgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEmNyeXB0b2dyYXBo
+eS5pbyBDQRcNMDIwMTAxMTIwMTAwWhcNMzAwMTAxMTIwMTAwWqAtMCswEgYDVR0U
+BAsCCQCrVKmM6x8K0zAVBgNVHRsBAf8ECwIJAKtUqYzrHwrSMA0GCSqGSIb3DQEB
+CwUAA4IBAQBQQTdnyuAhlijVgrTBnZdvP02ecT9fVhlBn8g7+ZKzP+TZ3leEvBrn
+fMyW9fsndQUSMSn7zZv6AIy+CknNMGpr9eeJ+cDyWcUmY+IsHUmBGbb8axfGTCzf
+OIfkP/rJF1XcwNFDNGDrXQZrIX4t+sXviQyezRrVNo59GHDUA+IO8kueASW9y60F
+Lf+aCv5I890OAUn749KtY50DDi+jgcdNPF256VZYNqDYGDQv3RN3wJ2/nuOBsKNL
+BY9Iup/CrrvhwPGi1gAGq0uDVDmN6DYYjMRmphda/ExzzulAtHCvEbb5Tin6EOnH
+dNMifa7LENOKFe9YqaKrOk6JckqLF7kn
-----END X509 CRL-----
diff --git a/vectors/cryptography_vectors/x509/custom/negative_serial.pem b/vectors/cryptography_vectors/x509/custom/negative_serial.pem
new file mode 100644
index 000000000..0994f9a25
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/negative_serial.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIELDCCAxSgAwIBAgIF+86ZbBMwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDU1vdGhlciBOYXR1cmUxEzARBgNVBAsTCkV2ZXJ5dGhpbmcx
+FjAUBgNVBAMTDU1vdGhlciBOYXR1cmUwHhcNMTYwNzA2MTgzNDA2WhcNMTYwOTE4
+MTgzNDA2WjCBmTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkZMMRQwEgYDVQQHEwtU
+YWxsYWhhc3NlZTEcMBoGA1UECRMTMzIxMCBIb2xseSBNaWxsIFJ1bjEOMAwGA1UE
+ERMFMzAwNjIxGDAWBgNVBAoTD0V4dHJlbWUgRGlzY29yZDEOMAwGA1UECxMFQ2hh
+b3MxDzANBgNVBAMTBmdvdi51czCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMu6VH/JvcG/foNel5R3NHz/OeI9fqHyoPB6d/wQ1k/aVGNotSzVaDCJPY3J
+xmr1KCnNjzGmViuaLXyZWZEMum2R8D0+LX1PHBQl2vbrXSOMDu97c323QOdTUwMY
+C2LmaFP3fa5SV5Q+8+4f/B97wXExOjp1z5z7VafYj2MoY72GitoSfJ/LrkKEksey
+fTflVxKEvZqW3wUN6F2Kj4Jo1N45Ym+lIrz/VQKDOSpc/p0dJ1PghDZZ2d2b3iuj
+5rCMTw9533WS3wueYfn70jJY9DKoFj9Ly6AG0AB2o7cqTv8j+3slVfAR3ufwgyx2
+ckUDBWCZaZdnhRxaj/G9MMYGEV0CAwEAAaOBwDCBvTAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdIwQHMAWAAwECAzANBgNVHQ4EBgQEBAMCATAbBgNVHREEFDASgggqLmdv
+di51c4IGZ292LnVzMAsGA1UdDwQEAwIBhjAgBgNVHSUBAf8EFjAUBggrBgEFBQcD
+AQYIKwYBBQUHAwIwPwYDVR0fAQH/BDUwMzAxoC+gLYYraHR0cDovL2NybC5zdGFy
+ZmllbGR0ZWNoLmNvbS9zZmlnMnMxLTE3LmNybDANBgkqhkiG9w0BAQsFAAOCAQEA
+bfqYztTkJPRPAJ1WItmU3RZIGRx1VkCABouAor6tVH6wGVCwWgaG8li6AujHMfYv
+y6QUPhhIyNjTe21ne72BY1XXd9haGdMwXtUCNfeGBXKsR9EN0kDyOAXGZWj3Fqpu
+S9WjluPAjQWHFoRwlQBSxCVuRgIrjXhJndvW9ySAaI51epRAr5kwylvTD7qy363C
+xDANx5XVFEktclI25DSrxmiJyawVGFjnwaYBFTe2ZINoZvs68EEl1b18+VGF21e9
+BAQGlcsIfbDAAEQFJ+5A+o8zy9M7CVsNVgw3TRJbjVTZSEg5PAEX+3C5V6wzrQi1
+nqzaNa/5DxGWILelZclgvA==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/custom/rsa_pss.pem b/vectors/cryptography_vectors/x509/custom/rsa_pss.pem
new file mode 100644
index 000000000..cdbc34d5c
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/rsa_pss.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDLTCCAhWgAwIBAgIUCD6ZpVYd5vCgzRh5ZIqYupE2VKIwDQYJKoZIhvcNAQEK
+MAAwJTESMBAGA1UECgwJYm9vdHN0cmFwMQ8wDQYDVQQDDAZyb290Y2EwHhcNMTYw
+MTAxMDAwMDAwWhcNNDAwMTAxMDAwMDAwWjAlMRIwEAYDVQQKDAlib290c3RyYXAx
+DzANBgNVBAMMBnJvb3RjYTCCAVYwQQYJKoZIhvcNAQEKMDSgDzANBglghkgBZQME
+AgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEFAKIDAgEgA4IBDwAwggEK
+AoIBAQCuXwLURTDREKWTeBxUQWQvj/hDVc0+PruZtBF5voNAZCjKSOKHFLasmCDw
+JuEHjj7ZHDF1JWZVGUbz3p5P+TiFmO/c1Wgb5IyAxdiDUGZvSVX3uC/X8EG/1MQz
+bwcDpqiadoIjL59jUJ0g2BJnx81NvpNgpe0rmK7aU52sPKJme31Ttd/lO8VJ3Mps
+lzpH0qzDJEcE3+lBF+AOJf2XDbPTFlbuPvDZHE5tVmdYC2IOad8U0Q/FLOhpMFOX
+j0n6tKf+Z14+7+xu7RV3gj/NMm0CXWG3ibTSOSrbyvreI0dHgZL57RdqCSE9scjA
+/1tD0a7UINhPBDZc6HaUqQUsQCPhAgMBAAGjITAfMB0GA1UdDgQWBBSpiALqV+wo
+zwcvMEvwYFLKe/vDPzANBgkqhkiG9w0BAQowAAOCAQEAEdp7sFyQA9g3Vk1KsrAB
+UFKqEe1a0azE4TRz2SRktRCswgv7iae0CiBGtPrzBNS6MlketixTfF1npEi7wuDn
+/00XRdgHCBIRGvemATx8oSP4qVrHUud2y/DLZOZBGYiasSHHgybsnikFZppGFp7m
+1D3Tti+GEsaANwRH5GW7h8f9hTMluwXlnNwyT/83yKq9Uih0eFEWHtf8hFswpCEK
+4swEBwBHUiCZs1O702H36xEnoayOWnIWAkV8ZccEjfbCHs+rnU+nGI5UfXg86VRb
+9iqcII7xyzPxb/HZRBusI9Uu/xiiqLjWqmx/ZMeadhiQndCoOj2yR8YT+G1BqcLa
+pA==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/custom/sia.pem b/vectors/cryptography_vectors/x509/custom/sia.pem
new file mode 100644
index 000000000..f745674f9
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/sia.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC7TCCAdWgAwIBAgICAwkwDQYJKoZIhvcNAQELBQAwDTELMAkGA1UEBhMCVVMw
+HhcNMTUwMTAxMDAwMDAwWhcNNDAwMTAxMDAwMDAwWjANMQswCQYDVQQGEwJVUzCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMF6/H53R0yqWqgwNhWKP/v3
+tSFoUboiMOXWq/zBxs/vWekj6hMwvFk7c4Aqtgim5KMwZSOjEWulqjlmFFF04Tts
+Sem3gGLkSdcu+xD9SekfoIuW0FHngun1q8W1pveYSCetuOc9oA8isu/c23bqtG7a
+2Y7WVmJ0P9xsDjNqXQzbqn3CnlNjXiTIelssQhWWgGPN62ipcrq7wePP8A+5qA43
+Kk0MLJINHozuMzzkcNwugUWtsFvymu4dJPFB6Mx4SYnFh/xvus2Xnz8hY8HXKZs2
+W8cv/ihI6Weu0eSNzFFbOlDtTeBP0FOEbKEKIjsQzIQcyA/evuRPMRTBPohq9YMC
+AwEAAaNXMFUwUwYIKwYBBQUHAQsERzBFMCEGCCsGAQUFBzAFhhVodHRwczovL215
+LmNhLmlzc3Vlci8wIAYDiDcHhhlnb3BoZXI6Ly9pbmZvLW1hYy1hcmNoaXZlMA0G
+CSqGSIb3DQEBCwUAA4IBAQB4AdYx02aXDJURPbZNi3j7FnK3LRVvJcq8vRHaG9b4
+soD/7qA8RJX11WTFNDY7g5OQhYT+WBc8OUinJaqJOPvEzgp5Prgq5AlAtcImvNX7
+dI3lr9esZ5gBWbsMK9saNEERhEZDUCSYW/GRMN4yxdUgTDPsfNr8N6bwfnGRR0xM
+EBr+p+fT1xth4uren7J/edYrY9a171y6bMdZQ1iVnFH2dFO25D+3k9sM6FRWWsWu
+mmrcg79QAl6jqC/6SkqVzpBPzi7dgGYluaKJjREC8e/cMcpphW1TP+8rZ161BmDk
+hk5/PrWguFuguWUyEkPH5oqFqoZuqeM0fULxHh2JiqOx
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed25519/ed25519-rfc8410.pem b/vectors/cryptography_vectors/x509/ed25519/ed25519-rfc8410.pem
new file mode 100644
index 000000000..3f4b5b2ac
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed25519/ed25519-rfc8410.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIBLDCB36ADAgECAghWAUdKKo3DMDAFBgMrZXAwGTEXMBUGA1UEAwwOSUVURiBUZX
+N0IERlbW8wHhcNMTYwODAxMTIxOTI0WhcNNDAxMjMxMjM1OTU5WjAZMRcwFQYDVQQD
+DA5JRVRGIFRlc3QgRGVtbzAqMAUGAytlbgMhAIUg8AmJMKdUdIt93LQ+91oNvzoNJj
+ga9OukqY6qm05qo0UwQzAPBgNVHRMBAf8EBTADAQEAMA4GA1UdDwEBAAQEAwIDCDAg
+BgNVHQ4BAQAEFgQUmx9e7e0EM4Xk97xiPFl1uQvIuzswBQYDK2VwA0EAryMB/t3J5v
+/BzKc9dNZIpDmAgs3babFOTQbs+BolzlDUwsPrdGxO3YNGhW7Ibz3OGhhlxXrCe1Cg
+w1AH9efZBw==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed25519/root-ed25519.pem b/vectors/cryptography_vectors/x509/ed25519/root-ed25519.pem
new file mode 100644
index 000000000..e509d5401
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed25519/root-ed25519.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIBODCB66ADAgECAgkAhPEIPRzjLZUwBQYDK2VwMBkxFzAVBgNVBAMMDklFVEYg
+VGVzdCBEZW1vMB4XDTE3MDQxOTIxMzYzOVoXDTQxMDIxMjIxMzYzOVowGTEXMBUG
+A1UEAwwOSUVURiBUZXN0IERlbW8wKjAFBgMrZXADIQAZv0QJaYTN/oVBusFn3DuW
+yFCGqjC2tssMXDitcDFm4aNQME4wHQYDVR0OBBYEFKKMwfhuWWDT4DrnXJYsl6jU
+SCk8MB8GA1UdIwQYMBaAFKKMwfhuWWDT4DrnXJYsl6jUSCk8MAwGA1UdEwQFMAMB
+Af8wBQYDK2VwA0EAa6iEoQZBWB1MhCzASv5HuFM7fR5Nz2/KM7GxYjQWsfvK2Ds1
+jaPSG7Lx4uywIndMafp5CoPoFr6yLBkt+NZLAg==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed25519/server-ed25519-cert.pem b/vectors/cryptography_vectors/x509/ed25519/server-ed25519-cert.pem
new file mode 100644
index 000000000..729ccfbd0
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed25519/server-ed25519-cert.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICHTCCAQWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
+IENBMCAXDTE3MDYxNDIzMzExOVoYDzIxMTcwNjE1MjMzMTE5WjASMRAwDgYDVQQD
+DAdFZDI1NTE5MCowBQYDK2VwAyEACkEMj+SRLjZSth3SIrG013cyYVN9frrVnfbN
+M2IqaT6jdjB0MB0GA1UdDgQWBBQqd22ipNHF0d+yJjFDgI/Jruq3rjAfBgNVHSME
+GDAWgBRwfy6ug2hZmAQjKs3rPhfNJN0BSTAJBgNVHRMEAjAAMBMGA1UdJQQMMAoG
+CCsGAQUFBwMBMBIGA1UdEQQLMAmCB0VkMjU1MTkwDQYJKoZIhvcNAQELBQADggEB
+AIdNMPRa2sgUW/qtCBWxmi0iVRoazl5pjU35cRl/ahBpI4pL5+fDVYuBzSOgEh7W
+6FUVix9mGvY9CK3ZkqrXCGRKeWnKrmdql5jrra5Qew43B+aZqa63639TGWqtm7Rk
+rWT14P7gma4K9Ea8eiXcT5NJ8sT7D2BOL0sL2alUmRT+k3YDUxiih7AiTkpo7f2Q
+x5l9f8qoRb6Skec+kuMQ4hIjBIe/3C+j4nqq9kDkJs8+VEaW7+7shSQzv0tnzBOl
+v5ty89x7LYAbGKvZNi8Z3814AWBWbYTskF0kW2/f6aZDpt239llYDazdErU1dEsS
+cc1gKHOG3zgz9wfih55M0dE=
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed448/root-ed448.pem b/vectors/cryptography_vectors/x509/ed448/root-ed448.pem
new file mode 100644
index 000000000..d1d4eaa92
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed448/root-ed448.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBgDCCAQCgAwIBAgICAcAwBQYDK2VxMBgxFjAUBgNVBAMMDUVkNDQ4IERlbW8g
+Q0EwIBcNMTkwODE1MTkzNzU2WhgPMjExOTA3MjIxOTM3NTZaMBgxFjAUBgNVBAMM
+DUVkNDQ4IERlbW8gQ0EwQzAFBgMrZXEDOgBf10SbWbRh/Sznh+xhatRqHaE0JIWn
+Dh+KDqddgOlneO3xJHabRscGG9Z4PfHlD2zR+hq+r+glYYCjUzBRMB0GA1UdDgQW
+BBRt4IpyNR7xrevKLNfx/aaRVK36TzAfBgNVHSMEGDAWgBRt4IpyNR7xrevKLNfx
+/aaRVK36TzAPBgNVHRMBAf8EBTADAQH/MAUGAytlcQNzAHx1CfZgc40PRGSiZTWC
+P8HQAFgAMwIh34cE4WSrb1m8fxv8/uMG0bIvIez/+PMx/ErKPMtyBC2+ACJCCL0Q
+In1OC28cIlpXIcQUFXamiGdg1Pd4NqAYl1BVNGWymHxf1AM/NNBPUhYxs1Qw1ape
+dJIjAA==
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ed448/server-ed448-cert.pem b/vectors/cryptography_vectors/x509/ed448/server-ed448-cert.pem
new file mode 100644
index 000000000..740f27554
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ed448/server-ed448-cert.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICHTCCAQWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
+IENBMCAXDTE4MDIyNzE1MDcxM1oYDzIxMTgwMjI4MTUwNzEzWjAQMQ4wDAYDVQQD
+DAVFZDQ0ODBDMAUGAytlcQM6ABBicYlhG1s3AoG5BFmY3r50lJzjQoER4zwuieEe
+QTvKxLEV06vGh79UWO6yQ5FxqmxvM1F/Xw7RAKNfMF0wHQYDVR0OBBYEFAwa1L4m
+3pwA8+IEJ7K/4izrjJIHMB8GA1UdIwQYMBaAFHB/Lq6DaFmYBCMqzes+F80k3QFJ
+MAkGA1UdEwQCMAAwEAYDVR0RBAkwB4IFRWQ0NDgwDQYJKoZIhvcNAQELBQADggEB
+AAugH2aE6VvArnOVjKBtalqtHlx+NCC3+S65sdWc9A9sNgI1ZiN7dn76TKn5d0T7
+NqV8nY1rwQg6WPGrCD6Eh63qhotytqYIxltppb4MOUJcz/Zf0ZwhB5bUfwNB//Ih
+5aZT86FpXVuyMnwUTWPcISJqpZiBv95yzZFMpniHFvecvV445ly4TFW5y6VURh40
+Tg4tMgjPTE7ADw+dX4FvnTWY3blxT1GzGxGvqWW4HgP8dOETnjmAwCzN0nUVmH9s
+7ybHORcSljcpe0XH6L/K7mbI+r8mVLsAoIzUeDwUdKKJZ2uGEtdhQDmJBp4EjOXE
+3qIn3wEQQ6ax4NIwkZihdLI=
+-----END CERTIFICATE-----
diff --git a/vectors/cryptography_vectors/x509/ocsp/ocsp-army.deps.mil-resp.der b/vectors/cryptography_vectors/x509/ocsp/ocsp-army.deps.mil-resp.der
new file mode 100644
index 000000000..08125f0a9
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ocsp/ocsp-army.deps.mil-resp.der
Binary files differ
diff --git a/vectors/cryptography_vectors/x509/ocsp/resp-sct-extension.der b/vectors/cryptography_vectors/x509/ocsp/resp-sct-extension.der
new file mode 100644
index 000000000..8018e2b82
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ocsp/resp-sct-extension.der
Binary files differ
diff --git a/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der b/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der
new file mode 100644
index 000000000..f89060d64
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der
Binary files differ
diff --git a/vectors/cryptography_vectors/x509/requests/challenge-invalid.der b/vectors/cryptography_vectors/x509/requests/challenge-invalid.der
new file mode 100644
index 000000000..dfea50244
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/requests/challenge-invalid.der
Binary files differ
diff --git a/vectors/cryptography_vectors/x509/requests/challenge-unstructured.pem b/vectors/cryptography_vectors/x509/requests/challenge-unstructured.pem
new file mode 100644
index 000000000..95a92ecb0
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/requests/challenge-unstructured.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICljCCAX4CAQAwFDESMBAGA1UEAwwJc29tZXRoaW5nMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEApDAVEIXi90VT6Q8sCYl0sdzZaxIW5fGtk5M8Vmoe
+iQbpWJtYZwQzOjOhgo9/+f/+Heg5gUI4+zUWyZMjh90KB5WrdTGO1x0yEUGjT15/
+VARFPmhyVniClEXPj4pANYVR00jMyvlLJuigKZbYR7VBTuE8oKOn2lu3eXuPFf6s
+8bLjSHLuTS7t13LDlrO1jh2RvSKeQDwQP7ZHWzjTASW3H6bZla8lSx/6Xhvk5aJQ
+JSMcEIYwPp7tP6+HV8E+FNjU19UZ3TsvGm60ZdoaCyFocgRFFju2wNSegmKzm00k
+bAum7RR4dcso58vrkUz5AbZchdQ3dh9rRsggxgV/F5lMkwIDAQABoD0wFQYJKoZI
+hvcNAQkHMQgMBmJlYXV0eTAkBgkqhkiG9w0BCQIxFwwVYW4gdW5zdHJ1Y3R1cmVk
+IGZpZWxkMA0GCSqGSIb3DQEBCwUAA4IBAQA3lwNp3HtDQjzkqxv9SvUCH6C9UEh0
+6+SWklP2ce2IWmoHHnfYW2SyPAhzR1q2gSu7IVZhM3WMEJRoiqN2ZFQed++0b91n
+LdUdCnDob8EFuX0AP7I4A9LI7G2bMS6mpzQBDXoo5hAlJV8I7Zq7NIby54bQiTgn
+B8cYopnmrLfCn1H8Su8oBgPNg3glOQSAkvZfqhHNTJyAnN+5+boFWpReAe8p/cfr
+kZh+fS8TcP7GbSLMnDlNwCAEIYRfAW7MVXJZ0l0tuDo7XdPImQgjjHYCk0tKPbeb
+LVyIAPNkMYLu7II79OOi8h1cZfU6wWwUIIhjMzjLpdZBPyhhGnUQzfuZ
+-----END CERTIFICATE REQUEST-----
+
diff --git a/vectors/cryptography_vectors/x509/requests/challenge.pem b/vectors/cryptography_vectors/x509/requests/challenge.pem
new file mode 100644
index 000000000..71ff39f24
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/requests/challenge.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICcDCCAVgCAQAwDTELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQCb+ec0zYAYLzk/MDdDJYvzdvEO2ZUrBYM6z1r8NedwpJfxUWqC
+hvK1cpc9EbQeCwS1eooTIGoNveeCrwL+pWdmf1sh6gz7SsxdN/07nyhSM8M6Xkec
++tGrjyi1H/N1afwWXox3WcvBNbxu3Df5RKLDb0yt9aqhmJylbl/tbvgJesXymwmp
+Rc1vXL0fOedUtuAJ3xQ15M0pgLF8qDn4lySJz25x76pMYPeN5/a7x+SR/jj81kep
+VaVpuh/2hePV5uwUX3uWoj5sAkrBCifi4NPge0Npd6KeKVvXytLOymH/4+WvV719
+wCO+MyrkhpdHSakJDTIaQIxsqVeVVKdPLAPJAgMBAAGgHjAcBgkqhkiG9w0BCQcx
+DwwNY2hhbGxlbmdlIG1lITANBgkqhkiG9w0BAQsFAAOCAQEAMmgeSa8szbjPFD/4
+vcPBr/vBEROFGgL8mX3o5pF9gpr7nRjhLKBkgJvlRm6Ma3Xvdfc/r5Hp2ZBTA7sZ
+ZYhyeezGfCQN/Qhda1v+sCwG58IjvGfCSS7Y5tGlEBQ4MDf0Q7PYPSxaNUEBH7vo
++M7U+nFuNSmyWlt6SFBSkohZkWoVSGx3KsAO+SAHYZ7JtqsAS/dm7Dflp8KxeDg7
+wzGBDQRpGF4CpI1VQjGSJQXSEdD+J7mtvBEOD34abRfV6zOUGzOOo3NWE6wNpYgt
+0A7gVlzSYpdwqjBdvACfXR2r/mu+4KkAvYh8WwCiTcYgGjl2pT1bO4hEmcJ0RSWy
+/fGD8Q==
+-----END CERTIFICATE REQUEST-----
diff --git a/vectors/setup.cfg b/vectors/setup.cfg
index 5e4090017..2a9acf13d 100644
--- a/vectors/setup.cfg
+++ b/vectors/setup.cfg
@@ -1,2 +1,2 @@
-[wheel]
+[bdist_wheel]
universal = 1
diff --git a/vectors/setup.py b/vectors/setup.py
index bf02e389f..482c01b35 100644
--- a/vectors/setup.py
+++ b/vectors/setup.py
@@ -15,20 +15,18 @@ base_dir = os.path.dirname(__file__)
about = {}
with open(os.path.join(base_dir, "cryptography_vectors", "__about__.py")) as f:
- exec(f.read(), about)
+ exec (f.read(), about)
setup(
name=about["__title__"],
version=about["__version__"],
-
description=about["__summary__"],
license=about["__license__"],
url=about["__uri__"],
author=about["__author__"],
author_email=about["__email__"],
-
packages=find_packages(),
zip_safe=False,
- include_package_data=True
+ include_package_data=True,
)